關於async和await的一些誤區例項詳解

2022-09-26 08:33:11 字數 1537 閱讀 3453

微軟官方的msdn上說async和await是「非同步」,但是不少人(包括筆者自己)都有一些誤區需要澄清:為什麼await語句之後沒有執行?不是非同步嗎?

先舉乙個示例**如下:

public partial class form1 : form

public form1()

private async void button1_click(object sender, eventargs e)

}很多人(包括筆者)一開始會覺得非同步好像類似多執行緒一樣,到await的時候會在後台先開啟乙個執行緒執行任務,隨後主線程(這裡是ui執行緒)將自動執行後面的部分(即彈出「button's event completed」的訊息框)。

其實這個理解是錯誤的。async和await的本質其實是「yield return」和「linq」的「迭代式」等待。我們應該清楚一點:那就是你寫了linq語句:

var results = from ……

select ……;

foreach(var r in results)

當你下斷點你會發覺results並不會立即執行,直到使用到results的地方(例子中也就是foreach這裡)才會被執行(此時黃色跟蹤除錯的光棒又會折回到var results……這裡,然後等到results執行完畢之後才真正進入foreach進行執行)。

所以,async/await和linq的這種「迭代式」的「非同步操作」是異曲同工的。只不過async/await本質是返回乙個task而已,而task又是非同步的(因為task本質就是乙個執行緒),所以真正執行到(使用到async方法的時候)帶有await的方法的時候,後台才會真正開啟乙個執行緒去執行任務。此時主線程會等待這個tas**程直到其執行完畢(iscomplete屬性為true為止)。所以介面是不會卡頓的。

所以,await是task的非同步等待而已,並不是我們所謂的「非同步操作」;拿它和linq作對比,你會發現linq執行順序和它一致,只不過linq沒有非同步等待(當然沒有!又沒有開啟執行緒啥的……)。

我們www.cppcns.com進一步可以這樣對比:

linq:變數 = linq語句(表示式)

等到使用linq變數的時候才折返到linq語句處真正執行linq語句。

非同步等待:變數 = 非同步方法

等hbpugw到使用await+非同步方法的時候才會折返到該非同步方法處,開啟線**正執行非同步方法,主線程被掛起(但不會造成介面死掉),直至子執行緒task任務完全執行完畢為止。

在linq中,你如果需要立即執行,可以使用擴充套件方法:

var results = (from ……

select ……).tolist();

因為立即使用到了這個linq語句,所以會被立即執行。

同樣地,非同步等待也可以變成類似wait一樣的同步等待:

private async void button1_click(object sender, eventargs e)

程式設計客棧

因為processing本來就返回task,當然也可以使用wait進行同步等待。

本文標題: 關於async和await的一些誤區例項詳解

本文位址:

async和await的講解

普通的函式宣告 async function a 複製 宣告乙個函式表示式 let a async function 複製 async形式的箭頭函式 let a async 複製 async與await例項應用,基礎 控制器呼叫與server中查詢資料 exports.getbloglist asy...

async和await的使用

async其實是es7的才有的,是非同步操作的進化,其實就是封裝乙個promise的物件返回 async function test console.log test promiseasync方法在普通的函式前加上 async 關鍵字即可。執行這個函式,發現並沒有返回1111,而是通過promise...

async和await的講解

async和await的講解 宣告async函式的幾個方法 普通的函式宣告 async function a 宣告乙個函式表示式 let a async function async形式的箭頭函式 let a async 初識async和await async與await例項應用,基礎 控制器呼叫與...