【问题标题】:Is Task.WhenAll required in the sample code?示例代码中是否需要 Task.WhenAll?
【发布时间】:2013-09-15 19:59:54
【问题描述】:

在下面的代码中task1和task2是相互独立的,可以并行运行。以下两种实现有什么区别?

var task1 = GetList1Async();
var task2 = GetList2Async();

await Task.WhenAll(task1, task2);

var result1 = await task1; 
var result2 = await task2; 

var task1 = GetList1Async();
var task2 = GetList2Async();

var result1 = await task1; 
var result2 = await task2; 

为什么我应该选择一个而不是另一个?

编辑:我想补充一下 GetList1Async() 和 GetList2Async() 方法的返回类型是不同的。

【问题讨论】:

  • I4v,在第一种情况下,var result = await task1;var result = task1.Result 完全相同。我确实认为.Result 更具可读性。
  • @I4V 不。在这两个 sn-ps 中,任务是并行运行的,而不是顺序运行的。
  • @dcastro,他们不一样。在出现异常的情况下,使用 .Result 会产生不同的异常(AggregateException),而不是使用await(第一个异常),因此在使用async/await 时,您应该更喜欢使用await 而不是@987654331 @ 保持异常行为一致。
  • 但是如果有异常会在 await all 的时候抛出,而且你永远不会到达下面的两行。假设您确实到达了下面的两行,您可以 .Result 而不用担心异常或死锁,因为它保证任务已经完成。参考stackoverflow.com/a/24657079/1676558
  • 我正在搜索这个案例,但仍然找不到我需要的文档。但是有一些人说:一旦你调用了一个异步方法,任务就会在调用时自动启动,并且 await 只等待它完成,如果任务完成它只返回结果。所以 await Task.WhenAll 在这种情况下只会增加更多的可读性。但是在几次看到这样的答案之后,我仍然不确定,如果你看过文档,你可能想在这里与我们分享。

标签: c# task-parallel-library async-await


【解决方案1】:

第一个结构更具可读性。 您明确表示您打算等待所有任务完成,然后再获得结果。我觉得用它代替第二个是足够合理的。

如果您添加第三或第四个任务,也减少写作...... IE。 :

await Task.WhenAll(task1, task2, task3, task4);

相比:

var result1 = await task1; 
var result2 = await task2; 
var result3 = await task3; 
var result4 = await task4; 

【讨论】:

  • 但是在第一个示例中,他无论如何都会等待所有组件任务。如果您避免这样做并改用 WhenAll 的返回值,这只是一个胜利。
  • 在这种情况下,什么是“胜利”似乎是主观的。 Task.WhenAll 与单独等待任务并不完全相同(正如 Servy 所知道的那样)。如果您想开始了解有关此问题的更多信息,请查看stackoverflow.com/q/18310996/1676558
【解决方案2】:

您的第一个示例将等待两个任务完成,然后检索两个任务的结果。

您的第二个示例将等待任务一次完成一个。

您应该使用对您的代码更清晰的那个。如果两个任务具有相同的结果类型,您可以从WhenAll 检索结果,如下所示:

var results = await Task.WhenAll(task1, task2);

【讨论】:

  • 除了意图清晰之外,如果条件正确(2 个或更多 CPU 内核空闲),解决方案 1 的并行机会是否大于解决方案 2?
  • @Snakebyte 不,没有。它们的性能相同,在第一种情况下只需要很少的额外开销,因为它不必要地执行WhenAll
  • @Servy:你到底是什么意思?据我了解,Stephan 指出,在 example1 中 task1 和 task2 是并行执行的。在示例2中它们不是并行执行的,任务1被执行,结果完成后主线程返回并开始执行任务2。
  • @BlackHawkDesign:不,在这两种情况下它们同时执行。问题是父方法是同时等待还是一次一个。
  • @Stephen Cleary:我明白你的意思,你/servery 是对的。我将第二段代码解释为: var task1 = await GetList1Async(); var task2 = 等待 GetList2Async();在这种情况下,他们将一个接一个地被处决。但你是对的,在这种情况下,它们都是并行执行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多