咨询区
-
Daniel Minnaar
我需要在 Console 程序中运行多个异步Task,在进一步处理之前我需要等待它们全部完成,我看了很多相关文章,但越来越糊涂,我知道可以将 task 链起来从而实现一个task的异步串行,但我希望多个task一起运行并在后续的某个点上一次获取所有的结果。.
请问是否有最简单的实现方式。
回答区
-
NtFreX
你可以使用 WhenAll
,它返回的是一个可等待的 Task 类,你也可以使用 WaitAll
,它没有返回值,但可以实现类似 Thread.Sleep
式的阻塞,直到所有的 tasks 完成,取消或者失败。
下面是一些详细的区别。
发生异常时
-
WhenALL
它会返回一个带失败状态的task,异常信息会包含在这个失败task的 AggregateException
中。
-
WaitAll
会直接抛出 AggregateException
异常。
任务被取消时
-
WhenALL
返回Task的任务状态是 TaskStatus.Canceled
。
-
WaitAll
会抛出 AggregateException
异常,内部的异常类型是 OperationCanceledException
。
线程阻塞
-
WhenALL
不会阻塞当前线程。
-
WaitAll
会阻塞当前线程。
参考如下代码:
var tasks = new Task[] {
TaskOperationOne(),
TaskOperationTwo()
};
Task.WaitAll(tasks);
// or
await Task.WhenAll(tasks);
-
Virus
完全可以使用阻塞版本的 Task.WaitAll
来实现。
List<Task> TaskList = new List<Task>();
foreach(...)
{
var LastTask = new Task(SomeFunction);
LastTask.Start();
TaskList.Add(LastTask);
}
Task.WaitAll(TaskList.ToArray());
当然你也可以用 async + await
再配 WhenAll
来实现完全异步,参考如下代码:
var cats = new List<Cat>();
var dog = new Dog();
var loadDataTasks = new Task[]
{
Task.Run(async () => cats = await LoadCatsAsync()),
Task.Run(async () => dog = await LoadDogAsync())
};
try
{
await Task.WhenAll(loadDataTasks);
}
catch (Exception ex)
{
// handle exception
}
点评区
这种等待多个 Task 的完成状态,一般都是用 WaitAll 和 WhenAll 两种方式实现,当然在 .NET6 中新增了 Parallel.ForEachAsync
方法来是实现异步并发,有兴趣的朋友可以了解下。