当前位置: 首页 > news >正文

异步进阶:C#的Task.WhenAll——如何开启多个异步任务

Task.WhenAll 是 .NET 中用于并行等待多个异步任务的核心方法。它可以让多个异步操作同时执行,然后一次性等待所有任务完成,而不是逐个等待。

async void Main()
{// 准备数据:[1,2,3,4,5,6,7,8,9,10]var inputs = Enumerable.Range(1,10).ToArray();var outputs = new List<int>();// ❌ 错误方式:串行执行(一个接一个)//foreach (var element in inputs)//{//    var result = await HeavyJobAsync(element);  // 等待当前任务完成//    outputs.Add(result);                       // 再开始下一个//}// 总耗时:10 × 200ms = 2000ms// ✅ 正确方式:使用 Task.WhenAll 并行执行var tasks = new List<Task<int>>();// 第一步:启动所有任务(不等待结果)foreach (var element in inputs){// 关键:这里创建并启动任务,但不 await,任务立即开始在后台执行tasks.Add(HeavyJobAsync(element));}// 第二步:使用 Task.WhenAll 等待所有任务完成await Task.WhenAll(tasks);  // 🎯 重点!// 第三步:收集所有任务的结果outputs = tasks.Select(t => t.Result).ToList();outputs.Dump();  // 输出:[1,4,9,16,25,36,49,64,81,100]
}// 模拟耗时异步操作
async Task<int> HeavyJobAsync(int input)
{await Task.Delay(200);  // 模拟200ms的工作return input * input;   // 返回平方值
}

分析

方式1的问题:
foreach (var element in inputs)
{var result = await HeavyJobAsync(element);  //这里会"阻塞"// 程序会在这里停下来等待,直到HeavyJobAsync完成// 然后才会执行下一次循环
}
方式2的优势:
// 第一步:快速启动所有任务
foreach (var element in inputs)
{tasks.Add(HeavyJobAsync(element));  // 只是启动,不等待// HeavyJobAsync立即返回Task对象,实际工作在后台进行
}// 第二步:统一等待所有任务完成
await Task.WhenAll(tasks);  // 一次性等待所有任务

Task.WhenAll 的不同用法

1. 有返回值的任务

// 启动多个任务
var task1 = GetDataAsync(1);
var task2 = GetDataAsync(2);
var task3 = GetDataAsync(3);// 等待所有任务并获取结果
int[] results = await Task.WhenAll(task1, task2, task3);
// results = [result1, result2, result3] 按顺序排列

2. 无返回值的任务

// 启动多个任务
var task1 = SaveDataAsync(data1);
var task2 = SaveDataAsync(data2);
var task3 = SaveDataAsync(data3);// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);

3. 动态任务集合

// 动态创建任务列表
var tasks = urls.Select(url => DownloadAsync(url)).ToList();// 等待所有下载完成
string[] contents = await Task.WhenAll(tasks);

使用场景

同时调用多个Web服务、同时读写多个文件、数据库操作:并行执行多个查询。

Task.WhenAny vs Task.WhenAll 核心区别

特性Task.WhenAllTask.WhenAny
等待策略等待所有任务完成等待任何一个任务完成
完成条件最慢的任务完成时最快的任务完成时
返回结果所有任务的结果数组第一个完成的任务对象
用途并行处理,需要所有结果竞争场景,只要第一个结果

http://www.dtcms.com/a/270617.html

相关文章:

  • ReactNative【实战系列教程】我的小红书 6 -- 购物(含商品搜索、商品分类、商品列表)
  • 编写产品需求文档:黄历日历小程序
  • [Leetcode] 预处理 | 多叉树bfs | 格雷编码 | static_cast | 矩阵对角线
  • React面试高频考点解析
  • LeetCode Hot 100 搜索二维矩阵 II
  • langchain从入门到精通(四十一)——基于ReACT架构的Agent智能体设计与实现
  • [附源码+数据库+毕业论]基于Spring Boot+mysql+vue结合内容推荐算法的学生咨询系统
  • RedisCommandExecutionException: ERR unknown command ‘LPOS‘
  • 树莓派5-系统 Debian 12 开启VNC远程访问踩坑记录
  • vue3面试题(个人笔记)
  • uniapp AndroidiOS 定位权限检查
  • ragflow_多模态文档解析与正文提取策略
  • 《设计模式之禅》笔记摘录 - 5.代理模式
  • Flutter基础(前端教程⑨-图片)
  • Robot之眼CMOS传感器静电防护指南
  • LeetCode热题100—— 32. 最长有效括号 (hard)
  • 零基础上手 Amazon DynamoDB:NoSQL 数据库服务的核心概念与快速搭建指南
  • Android-重学kotlin(协程源码第二阶段)新学习总结
  • 安全管理协议(SMP):配对流程、密钥生成与防中间人攻击——蓝牙面试核心考点精解
  • Qt自定义控件(9)——径向渐变QRadialGradient、圆锥渐变QConicalGradient
  • 华为OD机试_2025 B卷_观看文艺汇演问题(Python,100分)(附详细解题思路)
  • Amazon S3 对象存储服务深度解析:存储原理、应用场景与实战指南
  • Hexo + Butterfly + Vercel 完整个人Blog部署指南
  • 量子化学计算GPU化:ORCA与Gaussian的CUDA加速对比(电子积分计算中的Warpshuffle指令实战应用)
  • 如何给网页增加滚动到顶部的功能
  • 【具身智能】本地实时语音识别kaldi在正点原子RK3588上部署
  • Python标准库:时间与随机数全解析
  • python 异步编程事件循环的共享问题
  • 达梦:指定数据文件还原的路径
  • 【Linux | 网络】socket编程 - 使用TCP实现服务端向客户端提供简单的服务