我需要使用 Task.WhenAll 并发运行 3 个或更多任务,一旦 Task.WhenAll 完成执行所有任务,我想捕获所有任务的结果。
如何获取使用 Task.WhenAll 执行的那些任务的结果?
我应该使用.Result
还是await
?为什么呢?
.Result
会阻止吗?
这是代码示例:
var task1 = Task1();
var task2 = Task2();
var task3 = Task3();
await Task.WhenAll(task1, task2, task3);
// 1st approach:
var result1 = task1.Result;
var result2 = task2.Result;
var result3 = task3.Result;
// 2nd approach:
var result1 = await task1;
var result2 = await task2;
var result3 = await task3;
假设你想完成所有三个工作,并且它们都不依赖于另一个,那么在启动它们后分别使用Task.WhenAll()
和/或await
。您不一定需要同时使用两者。
var task1 = Task1();
var task2 = Task2();
var task3 = Task3();
异步方法始终同步开始运行。所以当你调用Task1()
时,它将运行到作用于不完整Task
的第一个await
。这将是它开始等待您发出的任何 I/O 请求的时候。此时,Task1()
返回一个不完整的Task
,执行继续进行下一行:运行Task2()
等。
这样可以充分利用资源,因为您利用等待响应的时间Task1()
在Task2()
等中启动下一个请求。
如果使用await Task.WhenAll
,则释放当前线程以执行其他工作。这三个任务很可能在完成等待(取决于一些事情(后在当前线程上恢复,一个接一个,无论它们各自的请求以什么顺序完成。一旦它们全部完成,执行将在await Task.WhenAll
之后继续下一行。
这:
var result1 = await task1;
var result2 = await task2;
var result3 = await task3;
与执行Task.WhenAll()
非常相似(因为您之前已经开始了任务(。但在这里,您正在捕获从每个返回的结果。如果您需要使用结果,那么您应该使用它。
如果您在await task1
之前使用Task.WhenAll()
,那么您将等待所有三个完成,然后再开始使用task1
的结果。如果可以在其他任务完成之前使用task1
的结果,则无需使用Task.WhenAll()
。
这:
var result1 = task1.Result;
var result2 = task2.Result;
var result3 = task3.Result;
将阻塞当前线程,直到task1
完成。如果需要在当前情况下恢复任务,这很可能陷入僵局。请参阅此处了解原因:不要阻止异步代码