Task.WhenAll

Task.WhenAll 是 .NET 中一个非常有用的工具,用于处理多个 Task 对象的并发执行。它允许你等待一组任务全部完成,并且可以对它们的结果进行统一处理。Task.WhenAll 是异步编程中常用的模式之一,尤其适合在需要并行执行多个任务时使用。

功能

Task.WhenAll 的主要功能是:
  1. 等待多个任务完成:它会等待传入的所有 Task 对象全部完成(无论是成功完成还是因异常而失败)。
  2. 返回结果:如果传入的任务是返回值的(即 Task<T> 类型),Task.WhenAll 会返回一个 Task<T[]>,其中包含所有任务的结果。
  3. 异常处理:如果任何一个任务抛出异常,Task.WhenAll 会将这些异常封装到一个 AggregateException 中,并在调用 ResultWait 时抛出。

基本用法

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.");
    }
}

注意事项

  1. 异常处理:如果任务中抛出异常,Task.WhenAll 会将所有异常封装到 AggregateException 中。你需要通过 AggregateException.InnerExceptions 来访问具体的异常。
  2. 性能优化:Task.WhenAll 不会启动任务,它只是等待已经启动的任务完成。如果你需要启动多个任务,可以使用 Task.Run 或直接创建任务。
  3. 取消支持:Task.WhenAll 支持 CancellationToken,可以在等待任务完成时取消等待。

适用场景

  • 并发任务处理:当你需要同时启动多个任务并等待它们全部完成时。
  • 结果聚合:当你需要处理多个任务的结果时。
  • 异常处理:当你需要统一处理多个任务的异常时。
总之,Task.WhenAll 是一个非常强大的工具,可以帮助你更高效地处理并发任务。
posted @   yinghualeihenmei  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2023-02-18 C# 运算符的优先级
点击右上角即可分享
微信分享提示