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
是一个非常强大的工具,可以帮助你更高效地处理并发任务。
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-02-18 C# 运算符的优先级