Task.WhenAll 和 Task.WhenAny 是 C# 中用于协调多个异步任务的核心工具,它们不直接执行并行计算,而是帮你“等待多个任务的完成状态”——一个等全部,一个等最先完成的那个。
Task.WhenAll:等所有任务都完成
当你有一组独立的异步操作(比如同时调用多个 API、读取多个文件),且必须等它们全部结束才能继续时,就用 WhenAll。它返回一个 Task(如果原任务是 Task
常见写法:
传入 Task[] 或 IEnumerableawait Task.WhenAll(task1, task2, task3)或
await Task.WhenAll(tasks)
Task.WhenAny:只等第一个任务完成
适用于“谁先回来就先处理谁”的场景,比如:对同一请求发起多个冗余服务调用(如不同 CDN 节点),取最快响应;或实现带超时的等待逻辑。
关键点:
返回的是 Task简单对比与选用建议
两者不是替代关系,而是解决不同问题:
需要聚合结果(如汇总所有接口数据)→ 用 WhenAll 需要快速响应或做“竞速选择”→ 用 WhenAny 想等所有任务但允许部分失败后继续?不能直接靠 WhenAll —— 得先把每个任务包装成不抛异常的版本(例如用task.ContinueWith(t => t.Exception?.InnerException)或 try/catch 包一层)
一个小提醒:别混淆“并发”和“并行”
WhenAll/WhenAny 本身不开启线程或强制并行;它们只是调度和等待已启动的异步任务。真正是否并发,取决于你传进去的任务本身(比如 HttpClient.GetAsync 是 I/O 异步,不占线程;Task.Run(() => CPUWork()) 才会用线程池线程)。所以不要以为用了 WhenAll 就自动多线程了 —— 它只是让等待更高效。
基本上就这些。用对场景,再注意异常处理和任务生命周期,这两个方法就很稳。
