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

C#中的 Task.WaitAll 与 Task.WhenAll

在C#中,Task.WaitAllTask.WhenAll 都是用于等待多个任务完成的方法,但它们在工作方式和使用场景上有重要区别。

1. 基本区别

Task.WaitAll

  • 同步阻塞:阻塞当前线程直到所有任务完成
  • 返回值:void
  • 异常处理:抛出 AggregateException

Task.WhenAll

  • 异步非阻塞:返回一个Task,不会阻塞当前线程
  • 返回值TaskTask<T[]>
  • 异常处理:返回的Task包含异常信息

2. 代码示例

Task.WaitAll 示例

async Task WaitAllExample()
{Task task1 = Task.Delay(1000);Task task2 = Task.Delay(2000);Task task3 = Task.Delay(1500);// 阻塞当前线程,直到所有任务完成Task.WaitAll(task1, task2, task3);Console.WriteLine("所有任务已完成");
}

Task.WhenAll 示例

async Task WhenAllExample()
{Task task1 = Task.Delay(1000);Task task2 = Task.Delay(2000);Task task3 = Task.Delay(1500);// 异步等待,不阻塞当前线程await Task.WhenAll(task1, task2, task3);Console.WriteLine("所有任务已完成");
}

3. 返回值处理

有返回值的任务

async Task<int> GetValue1() => await Task.Run(() => 1);
async Task<int> GetValue2() => await Task.Run(() => 2);
async Task<int> GetValue3() => await Task.Run(() => 3);// 使用 WhenAll 获取所有结果
async Task ProcessWithResults()
{Task<int> task1 = GetValue1();Task<int> task2 = GetValue2();Task<int> task3 = GetValue3();int[] results = await Task.WhenAll(task1, task2, task3);Console.WriteLine($"结果: {string.Join(", ", results)}"); // 输出: 1, 2, 3
}

4. 异常处理差异

Task.WaitAll 异常处理

void WaitAllExceptionHandling()
{Task task1 = Task.Run(() => throw new Exception("错误1"));Task task2 = Task.Run(() => throw new Exception("错误2"));try{Task.WaitAll(task1, task2);}catch (AggregateException ex){foreach (var innerEx in ex.InnerExceptions){Console.WriteLine($"捕获异常: {innerEx.Message}");}}
}

Task.WhenAll 异常处理

async Task WhenAllExceptionHandling()
{Task task1 = Task.Run(() => throw new Exception("错误1"));Task task2 = Task.Run(() => throw new Exception("错误2"));Task allTasks = Task.WhenAll(task1, task2);try{await allTasks;}catch (Exception ex){// 注意:WhenAll 只抛出第一个异常Console.WriteLine($"捕获异常: {ex.Message}");// 如果要获取所有异常,需要检查每个任务if (allTasks.IsFaulted && allTasks.Exception != null){foreach (var innerEx in allTasks.Exception.InnerExceptions){Console.WriteLine($"所有异常: {innerEx.Message}");}}}
}

5. 如何选择使用哪个

使用 Task.WaitAll 的情况

// 在同步方法中需要等待多个任务
void SynchronousMethod()
{// 在控制台应用或后台服务中var tasks = new[]{ProcessDataAsync(),SaveToDatabaseAsync(),SendNotificationAsync()};Task.WaitAll(tasks); // 阻塞直到完成Console.WriteLine("所有处理完成");
}

使用 Task.WhenAll 的情况

// 在异步方法中 - 推荐使用
async Task AsynchronousMethod()
{// 在Web API、UI应用或任何异步上下文中var tasks = new[]{ProcessDataAsync(),SaveToDatabaseAsync(),SendNotificationAsync()};await Task.WhenAll(tasks); // 不阻塞线程Console.WriteLine("所有处理完成");
}

6. 最佳实践建议

推荐使用 Task.WhenAll

public class DataProcessor
{// 好的做法 - 使用 WhenAllpublic async Task ProcessAllDataAsync(){var tasks = new List<Task>();for (int i = 0; i < 10; i++){tasks.Add(ProcessItemAsync(i));}await Task.WhenAll(tasks);}// 避免的做法 - 在异步代码中使用 WaitAllpublic async Task ProcessAllDataBadAsync(){var tasks = new List<Task>();for (int i = 0; i < 10; i++){tasks.Add(ProcessItemAsync(i));}// 可能造成死锁!Task.WaitAll(tasks.ToArray());}private async Task ProcessItemAsync(int item){await Task.Delay(100);// 处理逻辑}
}

7. 性能考虑

async Task PerformanceComparison()
{var stopwatch = Stopwatch.StartNew();// 使用 WhenAll - 更高效Task[] tasks = new Task[100];for (int i = 0; i < 100; i++){tasks[i] = Task.Delay(100);}await Task.WhenAll(tasks);Console.WriteLine($"WhenAll 耗时: {stopwatch.ElapsedMilliseconds}ms");// 重新计时stopwatch.Restart();// 使用 WaitAll - 可能造成线程阻塞tasks = new Task[100];for (int i = 0; i < 100; i++){tasks[i] = Task.Delay(100);}Task.WaitAll(tasks);Console.WriteLine($"WaitAll 耗时: {stopwatch.ElapsedMilliseconds}ms");
}

总结

特性 Task.WaitAll Task.WhenAll
阻塞性 同步阻塞 异步非阻塞
返回值 void Task 或 Task<T[]>
异常处理 AggregateException 通过返回的Task处理
使用场景 同步方法中 异步方法中
死锁风险 较高 较低
性能 可能阻塞线程 更高效

一般建议:在大多数现代C#开发中,特别是在ASP.NET Core、Web API、UI应用等场景下,优先使用 Task.WhenAll,因为它更符合异步编程模式,能避免死锁并提高应用响应性。

http://www.gsyq.cn/news/40678.html

相关文章:

  • 告别繁琐办公!这款本地PDF工具箱,安全高效才是硬道理!
  • 2025年11月解酒护肝产品实力榜:权威认证与用户体验深度评测
  • 2025 年文胸厂家最新推荐排行榜:调整型、养生、小胸、大胸等多类型文胸全覆盖,权威测评指引选品方向无钢圈/少女/大罩杯文胸公司推荐
  • 2025年6月AI搜索营销推荐榜:权威评测五强与五家备选
  • AI图像新纪元!Nano Banana带你玩转3D手办创作,人人都能成为设计大师!
  • [REPRINT] - SM4 - ENGINEER
  • 2025年6月deepseek关键词排名优化服务权威榜:五家机构对比评测
  • 2025年6月GEO优化权威推荐榜:五强对比评测与选型指南
  • Ansiable批量执行设置定时任务的脚本
  • 2025年6月GEO服务商推荐榜:五家对比看清优劣
  • 2025年6月GEO优化权威榜:五强对比评测助你决策
  • flanneld检查脚本
  • 深入解析:逻辑回归之参数选择:从理论到实践
  • 宝塔Linux部署 一个基于uni-app 系统指南
  • MySQL Binlog 疯涨问题终极解决方案:从配置到代码的全维度优化
  • 2025年质量好的螺旋压榨机厂家最新推荐权威榜
  • 2025年比较好的实木公寓床厂家推荐及选购指南
  • 2025年口碑好的重型三节轨厂家最新TOP排行榜
  • 2025 年磨粉机厂家最新推荐榜单:优质厂家深度解析,含超细 / 节能机型实力对比立式双动力磨粉机 / 节能磨粉机公司推荐
  • 给你10亿数据,如何做迁移?
  • 军工软件工业化突围: 重构智能版本管理的五大核心路径
  • C++ 随笔:用两个有序集合维护滑动窗口
  • ESXI 70 VCenter7.0
  • 太空舱民宿受欢迎的有哪些?太空舱民宿性价比高的有哪些?
  • 2025年质量好的150吨地磅厂家推荐及选购指南
  • 2025年11月脸颊有晒斑产品推荐榜:临床验证淡斑精华实测排名
  • 深入解析:Chrome扩展的“秘密通道”:深入解析Native Messaging的安全风险与防御
  • 2025年度太空舱生产厂售后排名:哪家售后好且更值得选
  • 2025年口碑好的护手霜厂家实力及用户口碑排行榜
  • 2025 年碟式离心机制造厂家最新推荐榜单:权威协会测评精选优质企业,为工业生产采购提供专业参考DB440 系列 / DB460 系列 / DB550 系列 / 专业碟式离心机推荐