C# Task.WhenAll和Task.WhenAny – 高效管理多个并行任务

2次阅读

Task.WhenAll等待所有任务完成,适合批量操作;Task.WhenAny响应首个完成的任务,适用于超时或降级场景。两者不启动任务,需先并行创建任务再传入,注意异常处理与并发控制。

C# Task.WhenAll和Task.WhenAny – 高效管理多个并行任务

Task.WhenAllTask.WhenAny 是 C# 中协调多个异步任务的核心工具,它们不执行任务,而是“观察”任务的完成状态,帮你决定下一步怎么走。

Task.WhenAll:等全部跑完再继续

当你需要所有异步操作都成功完成(比如批量获取用户数据、并行上传多个文件),就用 WhenAll。它返回一个新任务,这个任务在所有输入任务都完成后才完成;如果任一任务出错或被取消,它会立刻失败,并抛出包含所有异常的 AggregateException

  • 传入 IEnumerable<task></task>Task[],返回 Task;传入 Task<t>[]</t>,返回 Task<t></t>
  • 结果数组顺序与输入顺序严格一致,哪怕实际完成顺序不同
  • 注意异常处理:建议用 try/catch 捕获 AggregateException,再遍历 InnerExceptions 分析具体失败项

Task.WhenAny:谁先回来就先处理谁

适合“抢答”场景,比如设置超时、从多个服务中取最快响应、或实现降级逻辑。它返回一个 Task<task></task>,里面包裹最先完成的那个原始任务(无论成功、失败还是取消)。

  • 拿到结果后,要 await 那个内部 Task 才能真正读取值或捕获异常
  • 其余未完成的任务不会自动取消,需手动调用 CancellationTokenSource.Cancel() 或保留引用后续处理
  • 常配合 Task.Delay() 实现超时控制,例如:await Task.WhenAny(apiCall, Task.Delay(3000)) == apiCall ? ... : "超时"

别混淆:它们不是并发执行器

WhenAllWhenAny 本身不启动任务——你得先调用异步方法(如 GetDataAsync())拿到 Task 对象,再把它们传进去。常见错误是写成 WhenAll(GetDataAsync(), GetDataAsync()),这其实是同步调用两次,不是并行发起。

C# Task.WhenAll和Task.WhenAny – 高效管理多个并行任务

文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

C# Task.WhenAll和Task.WhenAny – 高效管理多个并行任务 4061

查看详情 C# Task.WhenAll和Task.WhenAny – 高效管理多个并行任务

  • 正确做法:先创建任务列表,再统一传入 WhenAll
  • 示例:var tasks = urls.select(u => HttpClient.GetAsync(u)); await Task.WhenAll(tasks);
  • 若想限制并发数(比如最多同时请求 5 个),要用 SemaphoreSlimParallel.ForEachAsync.net 6+)

选哪个?看你的业务意图

问自己一个问题:“我关心的是所有结果,还是第一个结果?”

  • 要汇总、校验、批量提交 → 选 WhenAll
  • 要快速响应、容错降级、避免等待 → 选 WhenAny
  • 两者可嵌套使用,比如用 WhenAny 控制整体超时,内部用 WhenAll 并行拉取子数据

基本上就这些。用对了,异步代码既清晰又健壮。

text=ZqhQzanResources