0
点赞
收藏
分享

微信扫一扫

如何同步等待多个异步 task 的返回结果 ?


咨询区

  • Daniel Minnaar

我需要在 Console 程序中运行多个异步Task,在进一步处理之前我需要等待它们全部完成,我看了很多相关文章,但越来越糊涂,我知道可以将 task 链起来从而实现一个task的异步串行,但我希望多个task一起运行并在后续的某个点上一次获取所有的结果。

请问是否有最简单的实现方式。

回答区

  • NtFreX

你可以使用 ​​WhenAll​​​,它返回的是一个可等待的 Task 类,你也可以使用 ​​WaitAll​​​,它没有返回值,但可以实现类似 ​​Thread.Sleep​​ 式的阻塞,直到所有的 tasks 完成,取消或者失败。

下面是一些详细的区别。

发生异常时

  1. WhenALL

它会返回一个带失败状态的task,异常信息会包含在这个失败task的 ​​AggregateException​​ 中。

  1. WaitAll

会直接抛出 ​​AggregateException​​ 异常。

任务被取消时

  1. WhenALL

返回Task的任务状态是 ​​TaskStatus.Canceled​​。

  1. WaitAll

会抛出 ​​AggregateException​​​ 异常,内部的异常类型是 ​​OperationCanceledException​​。

线程阻塞

  1. WhenALL

不会阻塞当前线程。

  1. 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​​ 方法来是实现异步并发,有兴趣的朋友可以了解下。

举报

相关推荐

0 条评论