C# Async & Await 非同步程式設計筆記

2022-06-15

筆記如何使用 C# Async & Await 語法特性,讓程式的處理量增加,不因為 IO Bound 的任務而造成整體的執行時間增加 😀

logo

程式實驗

public static class Cook
{
    public static async Task AppetizerAsync()
    {
        await Task.Delay(1000);
        Console.WriteLine("Salad Is Ready :)");
    }

    public static async Task MainCourseAsync()
    {
        await Task.Delay(3000);
        Console.WriteLine("Steak Is Ready :))");
    }

    public static async Task DessertAsync()
    {
        await Task.Delay(1000);
        Console.WriteLine("Cheese Cake Is Ready :)))");
    }
}

循序漸進的執行,與同步程式設計無異,花費的時間是各種任務之和。

var timeConsumed = sum(for task in tasks)
internal class Program
{
    static async Task Main(string[] args)
    {
        var start = DateTime.Now;
        await Cook.AppetizerAsync();
        await Cook.MainCourseAsync();
        await Cook.DessertAsync();

        Console.WriteLine($"Time consumed {DateTime.Now - start}");
    }
}

追求翻桌率的極致,任何一項 Task 都可以被執行,不在意順序,只要確保全部都有被執行即可 Task.WhenAll,花費的時間是所有任務中最大者。

var timeConsumed = max(tasks)
internal class Program
{
    static async Task Main(string[] args)
    {
        var start = DateTime.Now;

        var meals = new List<Task> { };
        meals.Add(Cook.AppetizerAsync());
        meals.Add(Cook.MainCourseAsync());
        meals.Add(Cook.DessertAsync());

        await Task.WhenAll(meals);

        Console.WriteLine($"Time consumed {DateTime.Now - start}");
    }
}

觀念筆記

使用 async 修飾的方法,被主方法呼叫後,主方法不會等待其回復,而逕自直接執行接續的工作,若再程式結束前,async 方法都尚未回應則就沒有機會回應了;如果主方法要等待 async 修飾方法,可以主動使用 await 進行等待。

  1. 多執行緒 (thread) 不等同於非同步程式設計 (async programming)。
  2. 非同步程式設計,無法提升程式性能 (performance),而是增加程式的處理量 (throughput)。程式變快是處理量上升所帶來的效益。
  3. CPU Bound 的任務使用非同步程式設計沒有幫助,要使用多執行緒;IO Bound 的任務則適合非同步程式設計。