如果你曾經有過按下一個按鈕執行某一段程式,

寫入檔案, 又或是讀取某一個網頁,

導致整個UI沒有反應或是無法在進行其他動作時,

這時應該就需要用到非同步的技巧…

以下練習[1]的非同步應用

image

先拉一個UI如下

image

private void button1_Click(object sender, EventArgs e)
{
    label1.Text = Sum().ToString();
    label2.Text = "計算完成";
}
private static long Sum()
{
    long sum = 0;
    for (int i = 1; i <= 100; i++)
    {
        sum += i;
    }
    SpinWait.SpinUntil(() => false, 10000); // 等待10秒
    return sum;
}

執行上述程式,的確發生在呼叫Sum副程式後,

整個UI沒有反應@@

------------------------------------------------------------

接下來, 利用 async/await 建立非同步:

image

方法1: 新增一個task實體, 語法如下

Task<回傳資料型態>(函式名稱)

button2_Click callback function 必須加入async關鍵字在void前, 不然函式中無法呼叫await

private async void button2_Click(object sender, EventArgs e)
{
    label1.Text = ""; label2.Text = "";
    var taskSum = new Task<long>(Sum);
    taskSum.Start();
    await taskSum;
    label1.Text = taskSum.Result.ToString();
    label2.Text = "(1)計算完成";
}
  1. image
  2.  
  3. 修改完成的非同步程式如下

方法2: 利用設計模式 Task.Factory.StartNew

PS. 不建立Task實體

image

private async void button3_Click(object sender, EventArgs e)
{
    label1.Text = ""; label2.Text = "";
    var ret = Task.Factory.StartNew<long>(Sum);
 
    label1.Text = ret.Result.ToString();
    label2.Text = "(2)計算完成";
}

 

結論: 個人覺得方法1比較直覺

(1) 新增一個task實體

(2) 啟動該實體(Start)

(3) 接著await該實體

方法2 把await也封裝在Factory裡面, 較(1)更簡單

 

------------------------------------------------

範例程式:AsyncAwaitApp

 

 

 

參考資料

1. 初探 async 和 await

2. 使用 Async 和 Await 設計非同步程式 (C# 和 Visual Basic)

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()