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

本文关键字:永远 tasks 查询 SQL 执行 WaitAll Task 异步 | 更新日期: 2023-09-27 18:31:52

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

异步任务都遵循 PumpLocsAsync() 的模式,其中对 MS SQL 的调用通过 BeginExecuteReader 异步调用;当读取器返回结果时,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);
                }
            }
....

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

你误解了如何调用Task.Factory.FromAsync(),你把BeginXxx方法的结果和一个委托传递给它EndXxx方法:

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

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