只有累積,沒有奇蹟

2025年1月16日 星期四

[NET] Task.WhenEach 等待多個任務的更靈活方式

前言
在過去如果要使用多個 Task 在 Dotnet 中可以使用 Task.WaitAll 和 Task.WhenAll 兩個內建的 API,其使用的差異之前也有撰寫文章 [NET] Task 等待多個任務 - Task.WaitAll 與 Task.WhenAll,這兩個方法都會等到所有任務完成後再繼續執行。如果當需求是完成一個就先進行處理,而不是全部完成後該怎麼辦呢 ? 這時就可以使用 Task.WhenEach 方法,來達到你所要的目的,這篇文章就簡單來介紹其概念與如何使用。

介紹
Task.WhenEach 是一種基於 Task.WhenAny 的模式,它的核心理念是當每個 Task 完成時立即執行對應的內容,而不用等待所有 Task 完成後再處理。這在某些場景下能提升應用的回應速度,尤其是當每個任務的執行時間不相同時,避免了某些較早完成的任務閒置等待其他長時間運行的任務,拖累到整體任務的完成時間。讓我們用一個範例來展示 Task.WhenEach 的概念。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
    static async Task Main(string[] args)
    {
        List> tasks = new List>
        {
            SimulateWork(1, 1000),
            SimulateWork(2, 2000),
            SimulateWork(3, 3000),
            SimulateWork(4, 4000),
            SimulateWork(5, 5000),
        };

        await TaskWhenEach(tasks);
    }

    static async Task SimulateWork(int id, int delay)
    {
        await Task.Delay(delay);
        Console.WriteLine($"Task {id} completed after {delay / 1000.0:F2} seconds");
        return id;
    }

    static async Task TaskWhenEach(IEnumerable> tasks)
    {
        var taskList = tasks.ToList();
        
        while (taskList.Any())
        {
            var completedTask = await Task.WhenAny(taskList);
            taskList.Remove(completedTask);
            Console.WriteLine($"Processed result: {await completedTask}");
        }
    }
}

  
  
簡單說明 Task.WhenEach 的運作方式
1. 建立多個非同步任務,這些任務模擬不同時間長度的工作。
2. 使用 Task.WhenAny 找到第一個完成的任務,立即處理結果。
3. 從列表中移除已完成的任務,然後繼續等待剩餘的任務。
4. 重複上述步驟直到所有任務完成。
這樣的設計確保了不會有執行緒閒置等待較長的任務結束,而是每當一個任務完成就立即執行處理邏輯,提升了 application 或功能的回應速度。

執行結果
Task 1 completed after 1.00 seconds
Processed result: 1
Task 2 completed after 2.00 seconds
Processed result: 2
Task 3 completed after 3.00 seconds
Processed result: 3
Task 4 completed after 4.00 seconds
Processed result: 4
Task 5 completed after 5.00 seconds
Processed result: 5

 

應用場景
即時資料處理:
- 當一組異步任務代表不同的 API 請求時,可以使用 Task.WhenEach 來立即處理已完成的請求,提升使用者體驗。
非同步串流處理:
- 當我們要處理大量非同步工作時,Task.WhenEach 可以確保已完成的工作不會閒置,而是立即傳遞到下一個處理步驟。
UI 更新:
- 在 UI 應用中,當我們需要執行多個背景任務,並希望它們完成後立即更新 UI,可以使用 Task.WhenEach 來確保 UI 變更即時發生。

小結
希望這篇文章能幫助讀者了解 Task.WhenEach 的基本概念與應用,如果有任何問題或建議,歡迎交流討論,happy Coding !

參考
Task.WhenEach 方法

0 意見:

張貼留言

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com