前言
在這篇中簡易介紹C#同步與非同步的作法。
一般我們在做一些任務時有時需要:
1.等待上個任務完成
2.同時處理多個任務
這時就會需要用到非同步、同步的作法,可以節省時間(在同個時間內處理多個任務)。
可能用到Thead或是用Task作法async
、await
。在這篇中則以:
https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/concepts/async/
作為範例,簡易的操作一個需要處理同步/非同步的範例。
同步範例實作
簡單來說,就是每個任務都是會等待上面的任務完成才依序執行。
下方以製作一份早餐的同步範例,1~7步驟都要等上面的步驟完成才會繼續。
1 | using System; |
結果:
可以發現這樣很難節省時間,所以其實能把某些部分拆成異步來做,有助於節省時間。(雖然同時間可能記憶體耗能會加大)
異步範例實作
準備早餐程式碼的簡單非同步版本看起來像下列程式碼片段:
FryEggsAsync、FryBaconAsync、MakeToastWithButterAndJamAsync更新為Task,函式使用Async
。
這時會變成先做第一步,之後2、3、(4+5)步是併發執行,並使用while做判斷,依序把完成的Task移除List,仍需處理的Task數量為0就跳出,代表完成了!
再由下個任務6繼續。
1 | using System; |
結果:
可以發現為異步執行!
FryEggsAsync:原本需6秒
FryBaconAsync:原本需6秒
MakeToastWithButterAndJamAsync:原本需3秒
以同步執行的話需要:15秒
在異步執行只需取其中最大的秒數:6秒
大幅度的減省時間花費。
TaskAPI 包含兩種方法, Task.WhenAll 和 Task.WhenAny 撰寫非同步程式碼,能在多個背景工作上執行非封鎖等候。await Task.WhenAny
await Task.WhenAll
更多可參考:
https://gist.github.com/relyky/52b4abf32b44d5d00a674b9cd34ca3a3
用紅筆畫起來部分,表示其併發執行。
結論
以Async為開頭的函數內步才能夠進行併發的操作。
並且搭配可以搭配await做Task的停頓。
即讓每個可Async的Task充分利用時間。
在工作上可能遇到需要併發、可同時執行時會使用,如有N個迴圈任務且沒有順序性,則可以寫入Task,或是需要用後端呼叫HTTP請求,可以一次併發,增加系統效率。或是有順序性執行的任務就很適合採用Task拆成子項目。
如果要再深入探討可以參考官方:
https://docs.microsoft.com/zh-tw/dotnet/csharp/async
參考資料
https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/concepts/async/
https://gist.github.com/relyky/52b4abf32b44d5d00a674b9cd34ca3a3
https://docs.microsoft.com/zh-tw/dotnet/csharp/async