当您在 C# 任务等待者上调用“OnComplete()”时,如何等待 OnCompleted 调用中给出的新作业

本文关键字:等待 调用 OnCompleted 何等待 作业 新作业 任务 OnComplete | 更新日期: 2023-09-27 18:18:57

我的Controller对象使用 Renci.SshNet 通过 SSH 调用 MySQL 数据库,由于我连接到多个数据库,我转向多线程,函数af.FetchAll()返回一个DataSet,所有这些都被添加到列表DataList<DataSet>,然后我要求所有任务完成,然后我会给我的 DataList to writer 对象以将其保存到 CSV 文件, 问题是:尽管我要求任务完成foreach (Task t in taskList) t.Wait();,但文件编写器尝试访问它时,awaiter.OnCompleted(() =>..etc中的代码仍在更新DataList,我如何确保等待者在我继续将"DataList"写入文件之前完成执行

    public void Query()
    {
        List<QueryValue> QueriesList = quryValLister.GetQueriesList();
        List<ConnectionValues> ConnectionsList = concValLister.GetConnectionList();
        // iterating over servers 
        List<Task> taskList = new List<Task>();
        foreach (ConnectionValues obj in ConnectionsList)
        {
            Controller af = new Controller(obj, QueriesList);
            Task<DataSet> taskDataResult = Task.Run (() => af.FetchAll());
            taskList.Add(taskDataResult);
            var awaiter = taskDataResult.GetAwaiter();
            awaiter.OnCompleted(() =>
            {
                DataSet temp = awaiter.GetResult();
                if (temp != null)
                {
                    MyDataList.Add(temp);
                }
            });
        }
        foreach (Task t in taskList) t.Wait();
    }

当您在 C# 任务等待者上调用“OnComplete()”时,如何等待 OnCompleted 调用中给出的新作业

您不应该在常规代码中使用GetAwaiter

如果要异步编写此内容,可以执行以下操作:

public Task QueryAsync()
{
  List<QueryValue> QueriesList = quryValLister.GetQueriesList();
  List<ConnectionValues> ConnectionsList = concValLister.GetConnectionList();
  // iterating over servers 
  var tasks = ConnectionsList
      .Select(obj => Task.Run(() => new Controller(obj, QueriesList).FetchAll()));
  MyDataList.AddRange(await Task.WhenAll(tasks));
}

或者,如果要同步编写它:

public void Query()
{
  List<QueryValue> QueriesList = quryValLister.GetQueriesList();
  List<ConnectionValues> ConnectionsList = concValLister.GetConnectionList();
  // iterating over servers 
  var tasks = ConnectionsList
      .Select(obj => Task.Run(() => new Controller(obj, QueriesList).FetchAll()))
      .ToArray();
  Task.WaitAll(tasks);
  foreach (var task in tasks)
    MyDataList.Add(task.Result);
}

请注意,同步版本中的错误处理是不同的;异常包装在 AggregateException 中。