C#中的異步編程Async 和 Await

談到C#中的異步編程,離不開Async和Await關鍵字編程

談到異步編程,首先咱們就要明白到底什麼是異步編程。 平時咱們的編程通常都是同步編程,所謂同步編程的意思,和咱們平時說的同時作幾件事情徹底不一樣。 在計算機的世界裏,同步編程的意思說 按照順序來執行,或者說是 一個接着一個地有序的來執行, 好比目前咱們在代碼中有三件任務來執行,那麼必須先執行完第1件,再執行第2件,接下來再執行第3件。 在這個過程當中,第1件沒有完成,你是無法開始作第2件事情的,必須等待。異步

好比一我的燒開水須要10分鐘,5分鐘找杯子,5分鐘找茶葉。 這件事情在同步編程的世界裏須要20分鐘完成,由於必須先燒開水10分鐘,等燒完開水後。 纔開始作第2件事情找杯子,花費5分鐘。 找完杯子後,纔開始作第3件事情-找茶葉,又花費5分鐘。這樣,整個過程就花費了20分鐘。但其實這3件事情能夠同時作,互相併不影響,這就是異步編程的概念了async

由上面這個例子中能夠發現,在計算機編程世界裏,【異步編程】纔是真正的同時進行事情,而【同步編程】是一件一件的有序執行。 上面的例子,若是採用異步編程,那麼10分鐘就能夠所有完成。異步編程

 

在C#中,異步編程中有三個方面須要注意:this

1.爲了表示一個方法是異步方法,須要使用async關鍵字來修飾該方法簽名spa

2. 異步方法的返回值類型 --- 只有 void, Task 和 Task<T>線程

3. 在異步方法內部,你須要使用await關鍵字來修飾一個能夠等待的【可等待】類型,來實現異步code

咱們經過例子來比較同步編程和異步編程的不一樣blog

舉例:  好比頁面上有個【計算】按鈕,點擊該按鈕 程序將會進行一個複雜運算,該運算將花費45秒的時間,運算完後返回計算結果,現實在頁面的一個textbox文本框裏面同步

private void btnCalculate_Click(object sender, EventArgs e)
{
     int calResult =   ToCalculate();
     this. Textbox1.Text = calResult;

}

private int ToCalculate()
{     
   // 這裏有複雜的計算過程,將耗時45秒, 咱們這裏經過讓線程休眠45秒鐘來模擬
     System.Threading.Thread.Sleep(45000); 
    
      return 100;

}

在上面代碼中,咱們假設方法ToCalculate方法要進行復雜的計算。在這裏,咱們經過讓當前線程掛起45秒,來模擬耗時45秒的複雜計算過程.

咱們能夠想象獲得,上面得代碼中,當用戶在界面上點擊btnCalculate按鈕時,UI在接下來的45秒裏將毫無反應,程序將只幹一件事情,就是容許ToCalculate方法來進行耗時45秒的複雜計算。45秒以後,纔會把計算結果返回到Textbox1中,再接下來作其餘的操做

這個顯然很是的用戶不友好,由於用戶會發現他須要等在那裏45秒,什麼事情也不能幹。若是在這個等待過程當中,用戶在UI上還能同時操做幹其餘的事情呢?  這個就須要涉及到異步編程的概念

【異步編程】的操做過程以下: 

執行異步方法,當遇到await關鍵字時,表示要開始執行一個異步方法,await關鍵字來修飾的方法是一個方法。這個時候程序會作兩件事情

第1件: 程序去執行await關鍵字修飾的異步方法

第2件: 在作第1件的同時,把控制權當即返回給調用者,也就是說調用者這個時候,能夠在等待異步方法執行的過程當中,同時去作其餘事情,由於控制權已經在它手中了。

 

看看上面的例子,若是採用異步方法,當用戶在界面上點擊btnCalculate按鈕時,程序會執行異步方法ToCalculate. 但與此同時,控制權也立刻回到UI手上,也就是說在後臺進行耗時45秒的複雜計算的同時,用戶能夠同時在UI上進行其餘操做。當異步計算結束,把計算結果顯示在UI的Textbox1上。

瞭解了整個過程後,咱們使用異步方法來改寫上面的代碼

private async void btnCalculate_Click(object sender, EventArgs e)
{
     int calResult =   await ToCalculate();
     this. Textbox1.Text = calResult;
}

private Task<int> ToCalculate()
{     
   //將複雜計算的過程放入一個Task<int>中,新開線程
   var t = Task.Run(()=>
   {
      System.Threading.Thread.Sleep(45000);
      return 100; 
   }); 
   //返回的是這個Task<int>
   return t;
}

 從上面的代碼變更中,咱們能夠看到幾處變更狀況

1. 在方法的簽名中,在public後面加入了async關鍵字, 將該方法標識成一個異步方法。 這樣,讓程序知道這個方法是一個異步方法, 此時它內部的await纔會被認爲是一個關鍵字。

    或者說,若是在方法的簽名中沒有async關鍵字, await會被認爲是一個普通的變量名,也就是說,它會被當成普通的C#標識符來處理(相似於 string await ="test";)  

2. 在async標識的異步方法中,在須要異步調用的方法ToCalculate方法前面,使用await關鍵字

3. 異步調用的方法ToCalculate,只能是三種返回值類型中的一種void, Task 和 Task<T>。 在這個例子中,是Task<T>

相關文章
相關標籤/搜索