You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Task.WhenAll后获取异步任务返回结果的正确方式是什么?

Task.WhenAll执行后获取任务结果的选型方案

结论

在已经await Task.WhenAll(params System.Threading.Tasks.Task[] tasks) 返回的任务后,优先选择再次await原始任务的方式获取结果,不推荐使用Task.Result属性。

核心原因

  • 异常处理更简洁直观

如果任务执行故障,Task.Result会将原始异常包装在AggregateException中抛出,需要手动拆包才能获取真实报错信息;而await会直接抛出任务的原始异常,无需额外解包操作,异常捕获逻辑更简单易读。就算已经通过Task.WhenAll捕获过全局异常,单独获取单个任务报错时,await的写法优势也十分明显。

  • 完全规避死锁风险

当前场景下任务已经执行完成,Task.Result不会触发同步阻塞,但代码会持续迭代修改:如果后续维护时移除了前面的await Task.WhenAll逻辑,Task.Result会立刻阻塞当前线程,在存在同步上下文的环境(比如WPF、ASP.NET Framework)中极大概率触发死锁;而await的写法哪怕删除了前置的WhenAll await,也始终是异步非阻塞的,不会引入死锁隐患,代码可维护性更强。

  • 兼容性更好

如果后续将普通Task<T>替换为性能更好的ValueTask<T>,await的写法无需做任何修改;而ValueTask<T>没有公开的Result属性,所有用到Task.Result的地方都要全部改写,适配成本更高。

  • 无额外性能开销

对于已经执行完成的任务,await操作会被编译器直接优化为返回结果,不会产生任何异步调度的额外开销,性能和读取Task.Result几乎一致,不需要担心写法更优会带来性能损失。

代码示例

Task<TResult1> task1= ...
Task<TResult2> task2= ...
Task<TResult3> task3= ...

await Task.WhenAll(task1, task2, task3)
// 推荐写法
var b = await task1; // 返回 TResult1
// 不推荐写法
var a = task1.Result; // 返回 TResult1

内容的提问来源于stack exchange,提问作者Autiarii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 07:12:03