真理:
本文示例通過test工程展現,控制台程式同理為啥我寫的非同步沒用?還是同步執行的?
上面這段**執行輸出:[
testclass
]public
class
asynctest
///
/// 非同步的方法
///
///
public
async
task
dosomethingasync()
public
async
task
asyncmethod1()
public
async
task
asyncmethod2()
public
task
sleepsomesecond
(int second)
}
可以看到,**並沒有非同步的執行asyncmethod1和asyncmethod2兩個方法,因為如果是非同步的話,測試程序會立即結束掉,而且從頭到尾都是同乙個執行緒在執行。begin:12
method1:12
method2:12
over
end:12
為啥???
請看下面這個非同步模型圖:
我們有呼叫方法,非同步方法,但非同步方法await的操作並不是非同步操作,而是簡單的sleep了一段時間。
什麼是乙個非同步操作?
c#非同步語法就兩個關鍵字,async
和await
,async
是在宣告非同步方法時使用的修飾符,await
表示式則負責消費非同步操作,即等待乙個非同步操作,換句話說,是包含以下含義的操作:
顯然,sleepsomesecond並沒有上述特點,除非方法呼叫結束,await處無法知道操作的狀態,因此**會一直執行直到返回task.completedtask,此時await發現任務已經執行完了,因此繼續執行await後面的**,整個過程看起來是同步的,而且是同一執行緒在跑的。簡言說,就是這個方法是不可等待的。
什麼是可等待的?
顯然task.delay(1000)
就是乙個最簡單的可等待的操作,不信你看:
因此上述**改為:
執行後輸出為:[
testclass
]public
class
asynctests")
;}public
async
task
dosomethingasync()
public
async
task
asyncmethod1()
public
async
task
asyncmethod2()
public
task
sleepsomesecond
(int second)
}
可以看到,程式一閃而過,在dosomethingasync中的第乙個await後直接執行main方法的後續**,可見整個過程非同步執行了!begin:12
開始執行method1
end:12
共耗時0.0010241s
此時在main方法最後加一行thread.sleep(5000);
,讓主線程阻塞5秒,輸出為:
可以看到,果然方法1和方法2都成功執行,且執行的執行緒相同,證明二者是同步執行的。不信將主線程阻塞改為3.5s,此時方法二將不會執行完畢。begin:12
開始執行method1
end:12
method1:10
開始執行method2
method2:10
dosomethingasync執行完畢
共耗時5.0020608s
值得注意的是,這個id為10的執行緒並不是async方法產生的,非同步本身不產生執行緒,而是與await配合去等待乙個非同步操作,這個非同步操作就是task.delay(),當**執行到await後,主線程便跳過此非同步方法去執行其它東西,系統分配乙個執行緒去執行task.delay()。你可能要問,為什麼非同步操作(sleepsomesecond方法)執行完成後會,同樣的執行緒會執行後面的**,因為設計就是如此精妙!(不然你說怎麼處理?)
非同步不等於多執行緒,使用非同步有什麼用?為什麼不直接使用task?
非同步外在表現也是通過乙個新執行緒去做一些事情,為啥不用過task.run直接new乙個task出來去做?意義就在乙個字上:await!task.run是不會等待任務執行成功的,除非你獲取結果或者wait它,這樣必然阻塞主線程。非同步的妙處就在與,主線程在執行到await處時,如果await的是乙個可等待的非同步操作,且此非同步操作還處於未完成的狀態,則會跳過await後的內容,回到呼叫方繼續執行,而這個非同步操作將由乙個新的執行緒繼續處理直至成功,在由這個所謂的新的執行緒繼續處理await下面的**,完全做到對主線程的不阻塞。
乙個非同步方法可以存在多個await嗎?
可以,上面的例子就已經有個兩個await,但是沒有實質效果。因為第乙個await後的所有內容(幾乎)都由同乙個執行緒執行。當然,如果非同步的操作中還有非同步的操作,這個非同步操作又會是乙個新的非同步方法,這樣的巢狀是有用的,這也是前面用了「幾乎」這個詞的原因!
C 非同步程式設計async await
async await使c 用以實現協程程式設計的方式,由task排程器統一排程每乙個非同步任務的執行,從排程器的執行緒池中拿出執行緒來執行,遇到await時執行緒會被 直到非同步方法執行完成 async本身沒有任何實際作用,只是在編碼期給程式設計師提示呼叫的方法為非同步,真正起作用的是await和...
C 非同步程式設計之async await
async和await這一組關鍵字是.net4.5新增的一種非同步程式設計方式,今天就根據自己的理解講講async和await與task之間的關係。拿作業系統來說,cpu就具有非同步性。當在進行io的耗時操作時,cpu不會處於阻塞狀態,而是可以繼續執行其它的指令。程式設計中非同步通常用於開啟大檔案 ...
C 非同步程式設計async await詳解
當函式使用async標記後,返回值必須為void,task,task,當返回值為task時,函式內部只需要返回t型別,編譯器會自動包裝成task型別,如下兩個函式執行結果一致 public taskf1 public async taskf2 await關鍵字必須在具有async標記的函式內使用,使...