天天看點

你眼中的async/await是什麼樣的?

又到了周末的code review環節,這次code review發現了一個對async/await的了解問題。讓我們直奔主題:

這是一段使用async/await的代碼,算得上是async/await的最佳使用實踐。問題出在大家對這段代碼了解各有不同,讓我們來看看如何了解這段代碼:

你眼中的async/await是什麼樣的?

這個了解正确嗎?團隊的争論焦點在步驟2上,大家錯誤的認為await關鍵字就是等待的意思,為了在第三步拿到結果,線程在步驟2處等待直到FoodSearchService傳回結果。如果你也是這樣了解的,那麼你應該看看下面的代碼如何了解?

剛才錯誤的了解正好是這段代碼的描述。那麼第一段使用async/await的代碼如何了解?

使用await标記的方法調用(上面例子中的foodsSearch)不會阻塞主線程,主線程在步驟2不會等待。

為了說明這個結論,我們用下面的代碼模拟await(僅僅是模拟其行為,并不能真确執行),我沒有研究過await的實作,但是下面的代碼跟await具有相同的行為:

為了友善大家了解,我們寫一個簡單的ICallBackRegister實作:

從上面模拟的代碼中我們可以得出兩個結論:

1、沒有任何阻塞主線程的代碼。

2、盡量推遲await的調用,能在步驟2使用await就不要在步驟1使用。因為一旦使用了await,後面所有的代碼都變成了await所調用對象的回調,無法跟之前的異步代碼并行。即便你在步驟1就使用了await,隻能說FoodSearchService和FruitSearchService兩者不能并行,但是任然不會阻塞主線程——在主線程上永遠沒有等待這一說。

我們再看張圖來解釋一下這期間發生的事情:

你眼中的async/await是什麼樣的?

設想這樣的代碼放在一個GUI中Button的click事件中,由于await不會阻塞主線程,界面再不會有假死的情況發生。

同樣的道理,在web mvc程式設計中,如果controller和EF中全程使用async/await,此時假設使用者有一個請求過來,IIS會從線程池中取出一個線程來響應使用者請求,由于主線程沒有任何阻塞,是以IIS會很快将線程回收到了線程池中。當EF傳回資料并且傳回ActionResult時,IIS再次從線程池中拿出一個線程來對使用者請求做響應。是以

正是由于async/await不會阻塞主線程,我們才說async/await會提高IIS的響應能力。

另外async/await的使用并不會提升通路資料庫的效率,該花多長時間還得花多長時間。

最後我們給出Task.Result版本的click事件,由于調用Task.Result會阻塞主線程,是以你可以看到界面假死的現象。

代碼下載下傳:download

作者:Richie Zhang

來源:http://www.cnblogs.com/richieyang/

聲明:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。