[英]In “truly asynchronous” code that uses async-await, isn't there still SOME “thread” that is stuck waiting?
假設我正確使用async
- await
,例如
await client.GetStringAsync("http://stackoverflow.com");
我知道,調用await
的線程變為“空閑”,也就是說,調用鏈上的某些內容不會卡在執行相當於
bool done = false;
string html = null;
for(; !done; done = GetStringIfAvailable(ref html));
如果我調用了GetStringAsync
的同步版本(按照慣例可能稱為GetString
),它將做的事情。
但是,這是我感到困惑的地方。 即使調用線程或應用程序可用線程池中的任何其他線程沒有被這種循環阻塞,也存在某種情況,因為據我所知,始終在低級別進行輪詢。 因此,我沒有減少工作量,而只是將工作推到了應用程序線程“下方”的某物……之類。
有人可以幫我清理一下嗎?
沒有。
編譯器會將使用async
/ await
in的方法轉換為async
為多個步驟的狀態機。 一旦await
被命中,方法的狀態就被存儲,執行被“卸載”回到調用它的線程中。 如果任務正在等待磁盤IO之類的事情,則OS內核最終將依靠物理CPU中斷來讓內核知道何時向應用程序發送信號以恢復處理。 加載未決方法的狀態,並在可用線程上排隊(如果ConfigureAwait
為true
,則在await
線程上單擊該線程;如果false
,則為任何空閑線程) (最后一部分並不完全正確,請參見Scott Chamberlain的文章)下面的評論。) 。 可以將其視為一個event
,應用程序在工作完成后要求硬件“ ping”它,而應用程序又恢復了之前的工作。
有些情況下,一個新的線程紡達做的工作,比如Task.Run
它確實在工作ThreadPool
線程,但在等待它完成沒有線程被阻塞。
重要的是要記住,使用async
/ await
異步操作都是關於暫停,存儲,檢索和恢復該狀態機的。 它實際上並不關心Task
發生的事情,那里發生的事情以及它如何發生,與async
/ await
沒有直接關系。
async
/ await
也讓我感到非常困惑,直到我真正了解該方法如何轉換為狀態機。 仔細閱讀由編譯器轉換為async
方法的內容可能會有所幫助。
您正在將其推到操作系統上-如果可以,它將運行其他線程,而不僅僅是等待。 當找不到任何要運行的線程時,它只會等待一個忙。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.