C 非同步程式設計Async await實踐與理解

2021-10-23 12:31:44 字數 2987 閱讀 9623

真理:

本文示例通過test工程展現,控制台程式同理

為啥我寫的非同步沒用?還是同步執行的?

[

testclass

]public

class

asynctest

///

/// 非同步的方法

///

///

public

async

task

dosomethingasync()

public

async

task

asyncmethod1()

public

async

task

asyncmethod2()

public

task

sleepsomesecond

(int second)

}

上面這段**執行輸出:

begin:12

method1:12

method2:12

over

end:12

可以看到,**並沒有非同步的執行asyncmethod1和asyncmethod2兩個方法,因為如果是非同步的話,測試程序會立即結束掉,而且從頭到尾都是同乙個執行緒在執行。

為啥???

請看下面這個非同步模型圖:

我們有呼叫方法,非同步方法,但非同步方法await的操作並不是非同步操作,而是簡單的sleep了一段時間。

什麼是乙個非同步操作?

c#非同步語法就兩個關鍵字,asyncawaitasync是在宣告非同步方法時使用的修飾符,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)

}

執行後輸出為:

begin:12

開始執行method1

end:12

共耗時0.0010241s

可以看到,程式一閃而過,在dosomethingasync中的第乙個await後直接執行main方法的後續**,可見整個過程非同步執行了!

此時在main方法最後加一行thread.sleep(5000);,讓主線程阻塞5秒,輸出為:

begin:12

開始執行method1

end:12

method1:10

開始執行method2

method2:10

dosomethingasync執行完畢

共耗時5.0020608s

可以看到,果然方法1和方法2都成功執行,且執行的執行緒相同,證明二者是同步執行的。不信將主線程阻塞改為3.5s,此時方法二將不會執行完畢。

值得注意的是,這個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標記的函式內使用,使...