当前位置: 首页 > 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.jsqmd.com/news/32075/

相关文章:

  • 2025年11月北京继承律师实力榜:十强对比与胜诉率数据全公开
  • IEEE Transactions 风格补充材料(Word)快捷排版教程
  • 2025年11月北京继承律师评测榜:继承纠纷律师团队权威榜单发布
  • Qoj2570. Maximal Subsequence
  • VS code中编写和运行C语言
  • Ansible常用模块分类
  • 2025年11月消防阀门厂家排名榜:国际认证与绿色制造指标评价
  • 告别繁琐办公!这款本地PDF工具箱,安全高效才是硬道理!
  • 用友U8删除应收凭证提示删除失败,使用Null无效
  • 2025年11月解酒护肝产品权威榜:蓝帽子认证与成分纯度全对比
  • 2025年11月解酒护肝产品实力榜:权威认证与用户体验深度评测
  • 黑龙江计算机培训专业公司推荐,资质齐全的计算机培训企业全解析
  • 2025年6月ai搜索排名优化推荐榜:五强对比评测与选型指南
  • 2025 年文胸厂家最新推荐排行榜:调整型、养生、小胸、大胸等多类型文胸全覆盖,权威测评指引选品方向无钢圈/少女/大罩杯文胸公司推荐
  • 2025年6月豆包搜索排名优化服务商榜:五强对比与实测排行
  • 2025年6月AI搜索营销推荐榜:权威评测五强与五家备选
  • AI图像新纪元!Nano Banana带你玩转3D手办创作,人人都能成为设计大师!
  • 2025年6月ai排名优化推荐排名榜:权威数据锁定五家优选
  • 2025年6月豆包关键词优化推荐榜:实测效果与口碑对比分析
  • 2025 年 11 月预埋件厂家推荐排行榜,幕墙预埋件,热镀锌预埋件,后置预埋件,槽式预埋件,冲压预埋件,焊接预埋件,套芯预埋件公司推荐
  • 2025年6月ai搜索排名优化推荐:五强榜单横评与选型攻略
  • [REPRINT] - SM4 - ENGINEER
  • 2025年6月GEO公司推荐榜:全维度对比评测一目了然
  • python常用数据结构之字典
  • 2025年6月GEO公司推荐榜:五强对比评测助你精准选型
  • 2025年6月deepseek关键词排名优化服务权威榜:五家机构对比评测
  • 液压位置控制源代码实现与解析(C语言+MATLAB联合方案)
  • 从编译到防护:AIoT 开发的 避坑 与 提速 实战
  • 2025年6月deepseek关键词排名优化权威榜:五家服务商综合评测对比
  • 2025年6月GEO优化权威推荐榜:五强对比评测与选型指南