談到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>