dr3x
dr3x

Reputation: 977

Async SQL query execution - Task.WaitAll(tasks) never completes

I have an app to move data from a MS SQL server into a MySQL server using async query execution; the data moves fine but Task.WaitAll(tasks) call in the RunAllTasks() method never completes.

The async tasks all follow the pattern of PumpLocsAsync() where the call to MS SQL is invoked asynchronously via BeginExecuteReader; when the reader returns with results, then MySQL inserts normally.

..

async Task PumpLocsAsync()
{
     using (var conn = new SqlConnection(SqlConnStr))
     using (var cn = new MySqlConnection(MysqlConnStr))
     using (var cmd = new SqlCommand())
     {
          cmd.Connection = conn;
          cmd.CommandText = "SELECT HERE";

          conn.Open();
          var handle = cmd.BeginExecuteReader();
          await Task.Factory.FromAsync(handle, (ar) =>
          {
               var rdr = cmd.EndExecuteReader(ar);
               var qry = @"INSERT HERE";

               cn.Open();
               using (var cmdm = new MySqlCommand(qry, cn))
               {
                   cmdm.CommandTimeout = MysqlCmdtimeout;
                   <PARAM SETUP HERE>
                   <COLUMN MAPPING HERE>

                   while (RetryUtility.RetryMethod<bool>(() => rdr.Read(), 3, 1000))
                   {
                       <LOADING PARAMS WITH BITS HERE>
                       RetryUtility.RetryAction(() => cmdm.ExecuteNonQuery(), 3, 1000);
                   }
               }
               Console.WriteLine("Finished Locs!");
               cn.Close();
          });
          conn.Close();
    }
}


...

        void RunAllTasks()
        {
            Task[] tasks = { PumpLocsAsync(), PumpPicsAsync() };

            try
            {
                Task.WaitAll(tasks);
                Console.WriteLine("Finished with all tasks...");
                foreach (var task in tasks)
                {
                    Console.WriteLine("Id: {0}, Status: {1}", task.Id, task.Status);
                }
            }

....

Upvotes: 2

Views: 3182

Answers (1)

svick
svick

Reputation: 244767

You misunderstood how to call Task.Factory.FromAsync(), you pass to it the result of the BeginXxx method and a delegate to the EndXxx method:

var rdr = await Task.Factory.FromAsync(
    cmd.BeginExecuteReader,
    (Func<IAsyncResult, SqlDataReader>)cmd.EndExecuteReader,
    null);

If you want to do something after the operation completes, simply put it below this line, await will make sure it executes at the right time.

Upvotes: 7

Related Questions