[C#.NET][TPL] 初探 async 和 await
.NET 4.5 新增了 async、await 兩個新的關鍵字,它們可以讓我們輕鬆的處理非同步,這要怎麼做呢?我們先從同步方法看起
Sum 方法模擬了耗時的處理,你會發現UI呆掉,不能處理其他事情..
private void button_SyncStart_Click(object sender, EventArgs e) { label1.Text = Sum().ToString(); label2.Text = "任務完成"; } private long Sum() { long sum = 0; for (int i = 0; i < 200; i++) { sum++; } SpinWait.SpinUntil(() => false, 10000); return sum; }
利用 async/await 建立非同步:
- 在 button_AsyncStart_Click 方法體加上 async 關鍵字,CLR 會將方法認為是非同步。
- 建立一個任務。
- 等待任務 await,CLR 會在這個關鍵字設下斷點,等工作完成後再執行下一行。
使用 Task<T>:
private async void button_AsyncStart_Click(object sender, EventArgs e) { label1.Text = ""; label2.Text = ""; var mainTask = new Task<long>(Sum); mainTask.Start(); await mainTask; label1.Text = mainTask.Result.ToString(); label2.Text = "任務完成"; }
使用 Task.Facktory.StartNew:
private async void button_AsyncStart_Click(object sender, EventArgs e) { label1.Text = ""; label2.Text = ""; var result = await Task.Factory.StartNew(() => Sum()); label1.Text = result.ToString(); label2.Text = "任務完成"; }
使用 Task.Run:
private async void button_AsyncStart_Click(object sender, EventArgs e) { label1.Text = ""; label2.Text = ""; var result = await Task.Run(() => Sum()); label1.Text = result.ToString(); label2.Text = "任務完成"; }
以往在處理非同步都要耗費很多的精力,常常一個工作硬生生會被拆成好幾段方法,維護起來是相當的痛苦,常常摸不著頭緒;這篇文章的範例程式碼很簡單,所以可能會對 async、await 兩個新的關鍵字無感,這要常有在處理非同步的人才會知道它們的好處。
建立非同步方法,以下出自MSDN
-
方法簽章包含一個 Async 或 async 修飾詞。
-
非同步方法的名稱以「Async」後置字元,按照慣例,結束。
-
傳回型別為下列其中一種型別:
-
Task<TResult> ,如果您的方法具有運算元具有型別參數的 return 陳述式。
-
Task ,如果您的方法沒有傳回陳述式也沒有 return 陳述式沒有運算元。
-
void (Visual Basic 中為 子函數 ),如果您撰寫一個非同步事件處理常式。
-
-
方法通常至少包含一個等候運算式,表示點方法無法繼續,直到等候的非同步作業已完成。 同時,方法暫停和控制項傳回到方法的呼叫端。
詳細資料可參考:http://msdn.microsoft.com/zh-tw/library/hh191443.aspx
所以我新增了一個SumAsync方法,程式碼如下:
private async Task<long> SumAsync() { return Sum(); }
可是這樣寫並沒有什麼太大的改變,所以我在 SumAsync 方法建立一個新的任務並回傳 Task<long>,當然結果都會跟上述的一模一樣
private async void button_AsyncStart_Click(object sender, EventArgs e) { label1.Text = ""; label2.Text = ""; var result = await SumAsync(); label1.Text = result.ToString(); label2.Text = "任務完成"; } private Task<long> SumAsync() { return Task.Run(() => Sum()); }
我希望用簡單的範例帶出 async/await 的用法,學習它們並沒有那麼難,本來想對照以前的寫法,但想想還是讓主題聚焦一點,於是放棄這樣的想法。
David 老師已經有這樣做,我們可以直接參考對照 http://studyhost.blogspot.tw/2012/06/metro-style-appnet-45.html
文章出自:http://www.dotblogs.com.tw/yc421206/archive/2013/06/14/105482.aspx
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET