首页 > 解决方案 > 如何在多个衍生的任务 ConfigureAwait 任务上“WaitAll”?

问题描述

我有一个生成多个任务线程的 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

标签: c#.net

解决方案


配置 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.

我还冒昧地将延续放在回调中。如果您出于任何原因不想这样做,请随时按照您在问题中的方式拆分它,它会以相同的方式工作。


推荐阅读