编辑
2025-10-11
C#
00

目录

Task.WaitAll 的特点
使用 Task.WaitAll 的基本语法
示例:使用 Task.WaitAll 等待多个任务完成
代码解析
示例:处理完成的任务结果
代码解析
示例:处理异常
代码解析
使用 Task.WaitAll 的注意事项
结论

在 C# 的多线程编程中,Task 类是处理异步操作的重要赋能,而 Task.WaitAll 方法则用于等待一组任务的完成。这在处理多个并行任务时非常有用,特别是在需要确保所有并发操作完成之前继续执行的场景中。本文将详细介绍 Task.WaitAll 的特点、用法,并提供多个示例以展示其应用。

这是个好玩意,以前thread中要同步这个费了事。

Task.WaitAll 的特点

  • 等待所有任务完成Task.WaitAll 方法接收一个任务数组,并阻塞当前线程,直到所有任务完成。
  • 简单易用:提供直接的方式来等待多个任务,可以通过简单的调用来确保所有任务都已完成。
  • 返回状态:如果所有任务完成,它会正常返回。如果任何任务引发异常,WaitAll 将会抛出相应的异常。
  • 适用于处理多个并行任务的结果:可以用在需要处理多个异步操作的结果时,方便地跟踪和管理任务的状态。

使用 Task.WaitAll 的基本语法

以下是 Task.WaitAll 的基本用法示例:

C#
using System.Threading.Tasks; Task[] tasks = new Task[3]; // 创建任务 Task.WaitAll(tasks); // 等待所有任务完成

示例:使用 Task.WaitAll 等待多个任务完成

以下示例展示了如何创建多个任务,并使用 Task.WaitAll 等待所有任务完成。

C#
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { Task[] tasks = new Task[3]; // 创建并启动多个任务 for (int i = 0; i < tasks.Length; i++) { int taskId = i + 1; // 为任务分配ID tasks[i] = Task.Run(() => { int delay = new Random().Next(1000, 5000); // 随机延迟 Thread.Sleep(delay); // 模拟耗时操作 Console.WriteLine($"任务 {taskId} 完成,耗时 {delay} 毫秒"); }); } // 等待所有任务完成 Task.WaitAll(tasks); Console.WriteLine("所有任务已完成。"); } }

image.png

代码解析

  1. 创建任务数组:初始化一个 Task 类型的数组,用于存储并发任务。
  2. 启动任务:使用 Task.Run() 方法启动多个任务,每个任务随机延迟一段时间后完成,并输出其完成信息。
  3. 等待所有任务完成:使用 Task.WaitAll(tasks) 等待所有任务完成,并输出提示信息。

示例:处理完成的任务结果

在实际应用中,我们可能需要处理完成的任务的结果。以下示例展示了如何获取每个任务的返回值。

C#
using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { Task<int>[] tasks = new Task<int>[3]; // 创建并启动多个任务 for (int i = 0; i < tasks.Length; i++) { int taskId = i + 1; // 为任务分配ID tasks[i] = Task.Run(() => { int delay = new Random().Next(1000, 5000); // 随机延迟 Thread.Sleep(delay); // 模拟耗时操作 Console.WriteLine($"任务 {taskId} 完成,耗时 {delay} 毫秒"); return delay; // 返回任务的耗时 }); } // 等待所有任务完成 Task.WaitAll(tasks); // 获取并输出所有任务的结果 foreach (var task in tasks) { Console.WriteLine($"任务耗时: {task.Result} 毫秒"); } Console.WriteLine("所有任务已完成。"); } }

image.png

代码解析

  1. 创建返回值任务:使用 Task<int> 数组存储任务,并返回每个任务的耗时。
  2. 启动任务:任务在完成后会返回随机耗时的值。
  3. 等待所有任务完成:使用 Task.WaitAll(tasks) 等待所有任务完成。
  4. 输出任务结果:循环所有任务,使用 task.Result 获取每个任务的耗时。

示例:处理异常

在多个任务并行执行时,任何一个任务抛出的异常都可以被捕获到。以下示例展示了如何处理任务中的异常。

C#
using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { Task[] tasks = new Task[3]; // 创建并启动多个任务 for (int i = 0; i < tasks.Length; i++) { int taskId = i + 1; // 为任务分配ID tasks[i] = Task.Run(() => { if (taskId == 2) { throw new Exception($"任务 {taskId} 遇到错误!"); // 故意抛出异常 } int delay = new Random().Next(1000, 5000); // 随机延迟 Thread.Sleep(delay); // 模拟耗时操作 Console.WriteLine($"任务 {taskId} 完成,耗时 {delay} 毫秒"); }); } try { // 等待所有任务完成 Task.WaitAll(tasks); } catch (AggregateException ex) { foreach (var inner in ex.InnerExceptions) { Console.WriteLine(inner.Message); // 输出异常信息 } } Console.WriteLine("所有任务处理完成。"); } }

代码解析

  1. 任务抛出异常:在某个任务中故意抛出异常,模拟任务处理错误的情况。
  2. 捕获异常:使用 try-catch 块包裹 Task.WaitAll(tasks),捕获 AggregateException,该异常包含所有任务引发的异常信息。
  3. 输出异常信息:遍历异常信息并输出。

使用 Task.WaitAll 的注意事项

  • 任务的状态Task.WaitAll 在所有任务完成之前会阻塞当前线程,确保在使用前已考虑对主线程的响应性。
  • 异常处理:在使用 Task.WaitAll 时应注意捕获异常,因为任何未处理的异常会导致 AggregateException 的抛出。
  • 资源管理:在任务已完成后可以安全地释放资源,确保并行计算不会导致资源泄漏。
  • 避免死锁:避免在当前线程中等待任务的完成,同时在其他线程中可能创建新的任务,从而可能导致死锁。

结论

Task.WaitAll 是 C# 中非常有用的工具,能够等待多个异步任务完成,非常适合需要确保所有并行工作完成的场景。通过上述示例,我们可以看到在实际应用中如何利用 Task.WaitAll 管理和处理并发任务。合理使用 Task.WaitAll 可以显著提高多线程程序的可靠性和效率,尤其在处理多个异步操作时,它为任务的组织和管理提供了极大的便利。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!