筆記如何使用 C# Async & Await 語法特性,讓程式的處理量增加,不因為 IO Bound 的任務而造成整體的執行時間增加 😀
程式實驗
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
進行等待。
- 多執行緒 (thread) 不等同於非同步程式設計 (async programming)。
- 非同步程式設計,無法提升程式性能 (performance),而是增加程式的處理量 (throughput)。程式變快是處理量上升所帶來的效益。
- CPU Bound 的任務使用非同步程式設計沒有幫助,要使用多執行緒;IO Bound 的任務則適合非同步程式設計。