【问题标题】:Task.WhenAll in async method, then unwrapping each task [duplicate]Task.WhenAll 在异步方法中,然后展开每个任务[重复]
【发布时间】:2018-06-14 10:19:02
【问题描述】:

我有两个任务可以并行运行以提高性能:

var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();

await Task.WhenAll(task1, task2);

现在,我确信这些任务已经完成。但根据我的理解(以及一些现实生活中的头痛),如果我在这些任务上调用.Result,我可能会导致死锁,即使它们已经完成?

根据我所阅读的内容,awaiting 完成的任务只会返回结果,所以看起来这就是要走的路。这让我的代码看起来很时髦:

var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();

await Task.WhenAll(task1, task2);

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

这是解决此问题并获得我的两项任务结果的正确方法吗?如果不是,有什么问题?有没有更好的方法来解开任务而不调用.Result

【问题讨论】:

  • 仅供参考,async 不平行
  • Task.WhenAll 是我指的并行部分
  • @maccettura 不,不是,但这里显示的代码 ,因为它启动多个异步操作而不等待其他操作完成,导致它们并行工作.
  • @Jonesopolis WhenAll 不会使工作并行运行。使其并行运行的原因是在另一项任务完成之前启动一项任务。
  • 你是对的。这就是我的意思 - 允许启动多个任务并等待它们全部完成。

标签: c# async-await task


【解决方案1】:

如果我在这些任务上调用 .Result,我可能会导致死锁,即使它们已经完成?

不,你不能。如果任务完成,Result 不会阻塞,它会立即返回,但更重要的是,您不能阻止正在等待的任务完成当它已经完成时

这是解决这个问题并获得我的两个任务结果的正确方法吗?

它肯定会工作。你当然是对的,它看起来很傻,因为你重复地等待任务两次(第二次实际上不会花费任何时间,因为它们已经完成了,你只是输入代码来等待它们两次)。你可以省略那些多余的代码,只需要一次等待它们:

var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();

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

【讨论】:

  • 哦,有道理。由于这两个任务都已启动,因此在效率方面会产生相同的结果。
  • 旁注:在从WhenAll 切换到单独的等待检查"multiple await vs. WhenAll" 上的讨论之前。
  • @AlexeiLevenkov 如果您想提出问题,为什么要链接到具有错误答案的问题作为最高和第二高答案?
  • 因为我不同意您的说法,即所有任务失败时的异常处理在两种情况下都是相同的(多个等待与WhenAll)。我很高兴看到为什么两者相同的解释,但不幸的是,您的 answer 目前并未涵盖该主题的这一部分。这就是为什么我试图将我的评论表述为通读讨论的建议,而不是盲目地站在讨论的一边。
  • @AlexeiLevenkov 在这两种情况下,如果两个任务都失败,那么调用方法返回的Task 将是第一个方法的异常。
猜你喜欢
  • 2016-10-27
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-27
相关资源
最近更新 更多