C#如何捕获任务会导致Task.WhenAll? “ .Result”或“ await”

时间:2019-12-04 15:48:40

标签: c# .net asynchronous async-await task

我需要使用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;

1 个答案:

答案 0 :(得分:2)

假设要完成所有三个作业,并且它们都不依赖另一个,则在启动它们之后分别分别使用, since you want to stack your和/或Task.WhenAll()。您不必同时使用两者。

await

异步方法总是开始同步运行。因此,当您调用var task1 = Task1(); var task2 = Task2(); var task3 = Task3(); 时,它将一直运行到对不完整的Task1()起作用的第一个await为止。那将是它开始等待您提出的任何I / O请求的时间。此时,Task返回不完整的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() 之前 Task.WhenAll(),那么在开始使用await task1的结果之前,您将等待所有三个操作完成。如果您可以在其他任务完成之前使用task1的结果,则无需使用task1

此:

Task.WhenAll()

将阻塞当前线程,直到var result1 = task1.Result; var result2 = task2.Result; var result3 = task3.Result; 完成为止。如果任务需要在当前上下文中恢复,则可能会陷入僵局。有关原因的说明,请参见此处:Don't Block on Async Code