C# Task.WhenAll 和 Task.WaitAll 介紹

Axios 同步等待 API 示範(Promise) 這篇文章中有示範 JavaScript 中的 Promise,主要是用來處理一個或多個非同步的回傳結果。在 C# 中也有類似的概念,就是 Task.WhenAll

Task.WhenAll

產生一個 當所有任務完成 時才會完成的任務
    
Task task1 = new Task(() =>
{
    Thread.Sleep(1_000);
    Console.WriteLine("Task 1");
});

Task task2 = new Task(() =>
{
    Thread.Sleep(2_000);
    Console.WriteLine("Task 2");
});

Task task3 = new Task(() =>
{
    Thread.Sleep(3_000);
    Console.WriteLine("Task 3");
});

task1.Start();
task2.Start();
task3.Start();
Console.WriteLine("Start tasks");

var whenAll = Task.WhenAll(task1, task2, task3);

whenAll.Wait();
Console.WriteLine("End whenAll");
    

注意: Task.WhenAll 並不會自動執行任務,需要將 Task 使用 Start() 開始執行,或是使用 Task.Run 建立後立刻執行。
補充:數字中的底線是C# 7.0 的 Literal improvements 功能,用來增加數字的可讀性,常用於當作千分位分隔符號。

Task 可以指定等待的時間,為了怕無限等待,最好限制等待時間,會回傳任務是否成功在時間內完成。
    
// whenAll.Wait();
bool wait = whenAll.Wait(3_000);
    

Task.WaitAll

上面的 Task.WhenAll 是產生一個任務,而 Task.WaitAll 則是直接等待,Task.WaitAll 就像是 直接加了 .Wait() 的 Task.WhenAll:
    
Task.WhenAll(task1, task2, task3).Wait();
    

實際範例:
    
Console.WriteLine("Start tasks");
Task task1 = new Task(() =>
{
    Thread.Sleep(1_000);
    Console.WriteLine("Task 1");
});

Task task2 = new Task(() =>
{
    Thread.Sleep(2_000);
    Console.WriteLine("Task 2");
});

Task task3 = new Task(() =>
{
    Thread.Sleep(3_000);
    Console.WriteLine("Task 3");
});
task1.Start();
task2.Start();
task3.Start();

Task.WaitAll(task1, task2, task3);
Console.WriteLine("End tasks");
    

注意: Task.WaitAll 也和 Task.WhenAll 一樣不會自動執行任務,需要將 Task 使用 Start() 開始執行,或是使用 Task.Run 建立後立刻執行。

Task.WaitAll 一樣可以限制執行時間和取得是否有執行完畢:
    
// Task.WaitAll(task1, task2, task3);
bool waitAll = Task.WaitAll(new Task[] { task1, task2, task3 }, 1500);
    



參考資料:
Microsoft.Learn - Task.WhenAll Method
Microsoft.Learn - Task.WaitAll Method
Microsoft.Learn - Async/Await - Best Practices in Asynchronous Programming

留言