[C#.NET][TPL] 初探 async 和 await

[C#.NET][TPL] 初探 async 和 await

.NET 4.5 新增了 asyncawait 兩個新的關鍵字,它們可以讓我們輕鬆的處理非同步,這要怎麼做呢?我們先從同步方法看起

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 建立非同步:

  1. 在 button_AsyncStart_Click 方法體加上 async 關鍵字,CLR 會將方法認為是非同步。
  2. 建立一個任務。
  3. 等待任務 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 = "任務完成";
}

以往在處理非同步都要耗費很多的精力,常常一個工作硬生生會被拆成好幾段方法,維護起來是相當的痛苦,常常摸不著頭緒;這篇文章的範例程式碼很簡單,所以可能會對 asyncawait 兩個新的關鍵字無感,這要常有在處理非同步的人才會知道它們的好處。


建立非同步方法,以下出自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

Image result for microsoft+mvp+logo