Task.WhenAll
Task.WhenAll 是 .NET 中一个非常有用的工具,用于处理多个 Task 对象的并发执行。它允许你等待一组任务全部完成,并且可以对它们的结果进行统一处理。Task.WhenAll 是异步编程中常用的模式之一,尤其适合在需要并行执行多个任务时使用。功能
Task.WhenAll 的主要功能是:-
等待多个任务完成:它会等待传入的所有
Task对象全部完成(无论是成功完成还是因异常而失败)。 -
返回结果:如果传入的任务是返回值的(即
Task<T>类型),Task.WhenAll会返回一个Task<T[]>,其中包含所有任务的结果。 -
异常处理:如果任何一个任务抛出异常,
Task.WhenAll会将这些异常封装到一个AggregateException中,并在调用Result或Wait时抛出。
基本用法
Task.WhenAll 可以接受一个 Task 数组或集合,也可以接受多个 Task 参数。以下是一些常见的用法:示例 1:等待多个任务完成
csharp复制
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Task task1 = DoWorkAsync(1);
Task task2 = DoWorkAsync(2);
Task task3 = DoWorkAsync(3);
// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("All tasks are completed.");
}
static async Task DoWorkAsync(int id)
{
Console.WriteLine($"Task {id} started.");
await Task.Delay(1000); // 模拟工作
Console.WriteLine($"Task {id} completed.");
}
}
示例 2:处理任务结果
如果任务有返回值(即
Task<T>),Task.WhenAll 会返回一个包含所有结果的数组。csharp复制
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Task<int> task1 = GetResultAsync(1);
Task<int> task2 = GetResultAsync(2);
Task<int> task3 = GetResultAsync(3);
// 等待所有任务完成并获取结果
int[] results = await Task.WhenAll(task1, task2, task3);
foreach (int result in results)
{
Console.WriteLine($"Result: {result}");
}
}
static async Task<int> GetResultAsync(int id)
{
Console.WriteLine($"Task {id} started.");
await Task.Delay(1000); // 模拟工作
Console.WriteLine($"Task {id} completed.");
return id * 10; // 返回结果
}
}
示例 3:处理异常
如果任何一个任务抛出异常,
Task.WhenAll 会将异常封装到 AggregateException 中。csharp复制
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Task task1 = DoWorkAsync(1);
Task task2 = DoWorkAsync(2);
Task task3 = DoWorkAsync(3);
try
{
await Task.WhenAll(task1, task2, task3);
}
catch (AggregateException ex)
{
foreach (var innerEx in ex.InnerExceptions)
{
Console.WriteLine($"Exception: {innerEx.Message}");
}
}
}
static async Task DoWorkAsync(int id)
{
Console.WriteLine($"Task {id} started.");
await Task.Delay(1000); // 模拟工作
if (id == 2)
{
throw new InvalidOperationException("Task 2 failed.");
}
Console.WriteLine($"Task {id} completed.");
}
}
注意事项
-
异常处理:如果任务中抛出异常,
Task.WhenAll会将所有异常封装到AggregateException中。你需要通过AggregateException.InnerExceptions来访问具体的异常。 -
性能优化:
Task.WhenAll不会启动任务,它只是等待已经启动的任务完成。如果你需要启动多个任务,可以使用Task.Run或直接创建任务。 -
取消支持:
Task.WhenAll支持CancellationToken,可以在等待任务完成时取消等待。
适用场景
-
并发任务处理:当你需要同时启动多个任务并等待它们全部完成时。
-
结果聚合:当你需要处理多个任务的结果时。
-
异常处理:当你需要统一处理多个任务的异常时。
总之,
Task.WhenAll 是一个非常强大的工具,可以帮助你更高效地处理并发任务。
浙公网安备 33010602011771号