Task.waitALL 和Task.WhenALL有什么区别?如何使用

Task.WaitAllTask.WhenAll 是两个不同的方法,它们都用于等待一组任务完成,但它们之间存在一些重要的区别。

Task.WaitAll

WaitAll 是一个同步方法,它会阻塞当前线程直到所有指定的任务完成。这意味着如果你在一个需要响应用户输入的线程上调用 WaitAll,那么这个线程将会停止响应,直到所有任务完成。因此,在 GUI 应用程序中不推荐在 UI 线程上使用 WaitAll

使用示例

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        var tasks = new Task[]
        {
            Task.Run(() => Task.Delay(1000)),
            Task.Run(() => Task.Delay(500))
        };

        try
        {
            // 这里会阻塞主线程直到所有任务完成
            Task.WaitAll(tasks);

            Console.WriteLine("All tasks completed.");
        }
        catch (AggregateException ex)
        {
            // 处理异常
            foreach (var innerEx in ex.InnerExceptions)
            {
                Console.WriteLine(innerEx.Message);
            }
        }
    }
}

Task.WhenAll

WhenAll 是一个异步方法,它不会阻塞调用线程,并且返回一个新的 Task<Task[]>,这个新任务在所有指定的任务完成后完成。你可以通过调用 Result 属性或使用 await 关键字来获取这些任务的结果或者等待它们完成。

使用示例

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var tasks = new Task[]
        {
            Task.Run(() => Task.Delay(1000)),
            Task.Run(() => Task.Delay(500))
        };

        try
        {
            // 这里不会阻塞主线程
            await Task.WhenAll(tasks);

            Console.WriteLine("All tasks completed.");
        }
        catch (AggregateException ex)
        {
            // 处理异常
            foreach (var innerEx in ex.InnerExceptions)
            {
                Console.WriteLine(innerEx.Message);
            }
        }
    }
}

总结

  • Task.WaitAll:

    • 同步方法。
    • 阻塞当前线程直到所有任务完成。
    • 不适用于 UI 线程。
    • 适合后台线程池线程或其他不需要立即响应的场景。
  • Task.WhenAll:

    • 异步方法。
    • 不会阻塞当前线程。
    • 返回一个任务,该任务在所有指定的任务完成后完成。
    • 可以安全地在 UI 线程中使用。

注意事项

  • 在使用 WaitAll 或者 WhenAll 时,如果任何一个任务抛出了异常,那么这些异常会被封装到一个 AggregateException 中。你需要捕获并处理这个异常来获取内部的异常信息。

  • 在使用 WhenAll 时,如果你在非异步上下文中使用它(即没有使用 asyncawait),你可能需要等待它的完成,例如通过调用 Result 或者 Wait 方法。

  • WhenAll 返回一个 Task<Task[]> 类型的对象,你可以通过访问 .Result 来获取已完成的任务列表。

  • 如果你需要对每个任务单独进行操作,考虑使用 Task.WhenAny 或者 Task.WhenAll 结合 LINQ 的 Select 方法。

posted @   .NET每天都很酷  阅读(226)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示