使用 Task.WaitAll 方法而不是 await 关键字[重复]

Posted

技术标签:

【中文标题】使用 Task.WaitAll 方法而不是 await 关键字[重复]【英文标题】:Using Task.WaitAll method instead of await keyword [duplicate] 【发布时间】:2021-09-17 13:13:21 【问题描述】:

我有以下 C# .NET 5 代码。基本上我打算异步调用这三个方法,即Fun1、Fun2和Fun3。这 3 种方法是独立的,因此是异步执行的候选方法。我真的要在这里使用关键字'await'吗?因为如果我在为所有 3 个方法调用调用 Task.Run 方法时使用 await 关键字,它将同步运行。所以我使用Task.WaitAll 来等待所有 3 个任务运行完成(阻塞主线程直到所有 3 个任务异步完成)。这种方法有什么问题吗?我不确定使用“await”实现此目的的替代方法是什么。截至目前,以下代码运行时间大约为 5 秒,这表明它是异步运行的。

using System;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;

    namespace MyTask
    
        class Program
        
            static async Task Main(string[] args)
            
                //Most articles use lamba expression but not sure why as I can directly pass function name to the Run method
                //var task1 = Task.Run(()=>  Fun1(); );
                //var task2 = Task.Run(()=>  Fun2(); );
                //var task3 = Task.Run(()=>  Fun3(); );
    
                var startTime = DateTime.Now;
                var task1 = Task.Run(Fun1);
                var task2 = Task.Run(Fun2);
                var task3 = Task.Run(Fun3);
                Task.WaitAll(task1, task2, task3);
                var duration = DateTime.Now.Subtract(startTime).TotalSeconds;
    
                WriteLine($"all done --total time taken is duration");
            
            static int Fun1()
            
                WriteLine("Within Fun1");
                Thread.Sleep(5000);
                return 1;
            
            static int Fun2()
            
                WriteLine("Within Fun2");
                Thread.Sleep(5000);
                return 2;
            
            static int Fun3()
            
                WriteLine("Within Fun3");
                Thread.Sleep(5000);
                return 3;
            
        
    

【问题讨论】:

await Task.WhenAll(...) 通常是更好的方法(尽管在当前情况下应该无关紧要)。至于“另类”——await task1; await task2; await task3;也可以用。 【参考方案1】:

Task.WaitAll() 会阻塞你的主线程。你应该使用await Task.WhenAll()

【讨论】:

我明白,我希望主线程等待结果,这很好,可以说我使用 WhenAll ,但我的实际问题是——说我们不需要 await 关键字是否正确在这种情况下? await Task.WhenAll(task1, task2, task3) 也阻塞了我的主线程,因为持续时间打印语句不会在 5 秒之前运行,这很好,因为我想等待结果.但是它和使用 Task.WaitAll 一样好,因为无论如何这也会阻塞 main。 @Dhiraj 如果您尝试在某些 WPF 应用程序中使用此代码,例如在某些回调中使用此代码,此行为将发生巨大变化) 当你说“我想等待”时,你可以使用 Task.WaitAll() 阻塞主线程直到所有任务完成,或者你可以等待 Task.whenAll() 释放你的等待任务完成时的主线程,并在所有任务完成后从同一行代码恢复。因此后者是一个非阻塞等待。

以上是关于使用 Task.WaitAll 方法而不是 await 关键字[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Task.WaitAll代替WaitHandle.WaitAll

带有异步 lambda 和 Task.WaitAll 的 Task.Factory.StartNew

Task.WaitAll和Task.WaitAny

NET问答: 多个 await 和 Task.WaitAll 是等价的吗?

c# Task waitAll,WhenAll

异步/等待死锁 Task.WaitAll 与 Task.WhenAll [重复]