2015年3月28日

C# async 和 await 控制基本教學

.net 4.5 中 async 和 await 的語法已經有很大的進步,用以下範例說明

1. 一個UI event handler 呼叫並且等待 AccessTheWebAsync 方法
2. AccessTheWebAsync 建立 HttpClient 實例 client,呼叫 client 的 GetStringAsync 方法,並立即回傳一個 Task ,其中 TResult 在這裡是一個 string 。
3. GetStringAsync 可能要等一個網站回應並且下載內容,但是因為 GetStringAsync 立即回傳一個 Task 並且把控制權交還給 GetStringAsync 的呼叫者,就是 AccessTheWebAsync 。
4. AccessTheWebAsync 繼續同步執行 DoIndependentWork 。
5. DoIndependentWork 執行完後控制權交還給 AccessTheWebAsync。
6. AccessTheWebAsync 想要接著做下面的工作,必須取得 GetStringAsync 的 Task 的結果,所以這裡使用 await 來等待結果,這樣執行權會交還給 AccessTheWebAsync 的呼叫者,就是一開始的 UI event handler,這個時候會把 AccessTheWebAsync 的狀態儲存起來以便之後使用。(這裡我的理解是,只要在一個 code block 碰到 await 就會等待,即使有不需要結果也能執行的程序,也不會先執行,都會等)
7. 當 GetStringAsync 完成了工作, await 會從 getStringTask 裡面取得 Task 的結果,並傳給 urlContents 。
8. 回傳結果,並讓處於等待狀態的 UI event handler 繼續執行。

理解要點:

1. await 不會阻止該 async 的 thread 的執行,await 是把剩下的程式變成後續程式(continuation)並且把控制權交給 async 的 caller 。
2. async 和 await 不會產生新的 thread ,async 方法不需要 multithreading ,因為 async 方法不是跑在他自創的 thread ,而是跑在當前同步的情境中( context ),只有在一個方法是執行狀態的時候才會花 CPU 時間。
3. 這種實作方法相對於 BackgroundWorker 的好處是語法簡單而且不用擔心 race condition。



Good video
http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DEV-B319#fbid=

小重點:
async 可以搭配 void, Task, Task 來使用,如果方法沒有回傳值應該使用 async Task 而不是 async void ,async void 一般使用在最頂層的 event handler ,async void 相當於射後不理,讓其他的 UI 介面可以繼續回應使用者,其他情況應該避免使用 async void ,以免造成結果沒有產生就回傳了,或是 race condition等情況。
使用 async void 的時候,例外狀況要在呼叫的方法的內部處理,因為外部立即返回所以會離開外部try...catch的範圍。
另外 async 方法應該一路使用到底,比較好除錯。





沒有留言:

張貼留言