如何在多个产生的Task ConfigureAwait任务上“ WaitAll”?

时间:2019-09-20 17:41:28

标签: c# .net

我有一个C#控制台应用程序,它会产生多个任务线程。在退出应用程序之前,我需要等待它们全部完成,否则它将关闭所有线程。如何在ConfiguredTaskAwaiter上执行“ .WaitAll()”(我假设这就是我要观看的内容)

foreach (var entityType in entityTypes)
{
     // Create a task for each entity to thread the calls
     var task = Task.Run(() => TestTaskAsync(entityType)).ConfigureAwait(false); // Long running process
     var awaiter = task.GetAwaiter();
     Action showComplete = () => OnComplete($"PROCESSING FOR ENTITY ({entityType.Id}) HAS COMPLETED.");
     awaiter.OnCompleted(showComplete);
}

// Should not continue until all tasks have completed

2 个答案:

答案 0 :(得分:1)

Configure await并不会更改任务本身的任何属性,它只是告诉编译器您在等待任务后是否在意当前上下文。因此

var task = Task.Delay(1000);
// ...
await task.ConfigureAwait(false);

相同
var task = Task.Delay(1000).ConfigureAwait(false);
// ...
await task;

在您的特定情况下,为您实际上不打算等待的任务配置等待是没有意义的。您应该汇总它们,然后等待它们全部在一起。

您可能想做的是

var tasks = new List<Task>();

foreach (var type in types)
{
    var task = Task.Run(() =>
    {
        TestTaskAsync(entityType);
        OnComplete($"PROCESSING FOR ENTITY ({entityType.Id}) HAS COMPLETED.");
    });
    tasks.Add(task);
}

await Task.WhenAll(tasks).ConfigureAwait(false);

这告诉编译器,您不在乎等待后的上下文。由于您不等待单个任务,因此在等待这些上下文后再担心上下文是没有意义的。您将只等待代表所有任务的任务,即Task.WhenAll返回的任务。

我也自由地将延续放在回调中。如果您出于某种原因不想这样做,请随意按照问题的方式进行拆分,该方法将以相同的方式工作。

答案 1 :(得分:0)

var taskList = new List<Task>();

foreach (var entityType in entityTypes)
{
    ....
    taskList.Add(task);
}

Task.WaitAll(taskList.ToArray())

,但是您应该然后使用名为 WhenAll 的异步版本:

await Task.WhenAll(taskList)