异步SQL查询执行 - Task.WaitAll(tasks)永远不会完成

时间:2012-04-22 19:37:27

标签: c# asynchronous async-await

我有一个应用程序,可以使用异步查询执行将数据从MS SQL服务器移动到MySQL服务器中;数据移动正常,但RunAllTask​​s()方法中的Task.WaitAll(tasks)调用永远不会完成。

异步任务都遵循PumpLocsAsync()的模式,其中通过BeginExecuteReader异步调用对MS SQL的调用;当读者返回结果时,MySQL会正常插入。

...

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);
                }
            }

....

1 个答案:

答案 0 :(得分:7)

您误解了如何致电Task.Factory.FromAsync(),您将BeginXxx方法的结果和EndXxx方法的委托传递给它:

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

如果您想在操作完成后执行某些操作,只需将其放在此行下方,await将确保它在正确的时间执行。