簡體   English   中英

在 'async' 方法上到達 'await' 時線程會發生什么?

[英]What happens to the thread when reaching 'await' on 'async' method?

正如標題所暗示的那樣,我的問題是關於“異步”和“等待”的背景。

是不是說當前線程到達 'await' 關鍵字,就進入“睡眠”狀態,等待方法完成后喚醒?

謝謝!

蓋伊

說當前線程到達'await'關鍵字是什么,它會進入“休眠”,並在await方法完成時喚醒,這是真的嗎?

不。 async的全部意義在於,當他們可以做其他工作時避免讓線程處於休眠狀態。 另外,如果運行async方法的線程是一個UI線程,那么你真的不希望它在休眠 - 你希望它可用於其他事件。

當執行到達await表達式時,生成的代碼將檢查您正在等待的事物是否已經可用。 如果是,你可以使用它並繼續前進。 否則,它將為“等待”部分添加延續並立即返回

繼續確保在等待值准備好時運行異步方法的其余部分。 發生在哪個線程取決於您正在等待的上下文 - 如果異步方法在線程池線程中運行,則延續可以在與該方法啟動的線程不同的線程上運行...但是不應該物。 (其余的上下文仍將傳播。)

請注意,async方法在沒有完成的情況下返回是很好的 - 因為異步方法不能直接返回值 - 它總是返回一個Task<T> (或Task ,或void )...並且返回的任務由只有當異步方法真正到達終點時才會完成方法。

不。當前線程實際上不會進入睡眠狀態。 執行繼續。 這是它的全部技巧。 您可能有一些代碼處理數據,而異步操作仍處於待處理狀態。 這意味着當異步完成時,您的主線程可以自由運行並處理其他數據。

至於問題的另一部分 - 異步只是在另一個線程上執行,而不是當前線程。 我相信CLR負責旋轉這些線程,因此允許同時執行許多異步操作(即,您可能同時從不同的Web服務器異步檢索數據)。

async只是允許使用await關鍵字的語法糖。

如果在 ASP.NET Core 中使用了async, await ,那么您的請求線程將被釋放到線程池中。

正如斯蒂芬·克利里所說:

異步請求處理程序的操作方式不同。 當一個請求進來時,ASP.NET 使用它的一個線程池線程並將它分配給那個請求。 這次請求處理程序將異步調用該外部資源。 這會將請求線程返回到線程池,直到對外部資源的調用返回。 圖 3 說明了在請求異步等待外部資源時具有兩個線程的線程池。

在此處輸入圖片說明

重要的區別是請求線程在異步調用過程中已經返回到線程池中。 當線程在線程池中時,它不再與該請求相關聯。 這一次,當外部資源調用返回時,ASP.NET 使用其線程池線程之一並將其重新分配給該請求。 該線程繼續處理請求。 當請求完成時,該線程再次返回到線程池。 請注意,對於同步處理程序,請求的生命周期使用相同的線程; 相比之下,對於異步處理程序,不同的線程可能會分配給同一個請求(在不同的時間)。

對於桌面應用程序:

await釋放當前線程,但不會釋放到線程池。 UI 線程不是來自線程池。 如果您運行異步方法,例如ExecuteScalarAsync沒有async, await關鍵字,那么無論如何該方法都將異步運行。 調用線程不會受到影響。

特別感謝Panagiotis Kanavos 的精彩評論。

例如,您有一個繁重的存儲過程,並且您的存儲過程需要 10 分鍾才能執行。 如果您在沒有async, await關鍵字的情況下從 C# 運行此代碼,那么您的執行線程將等待您的存儲過程 10 分鍾。 而這個等待線程什么都不做,它只會等待存儲過程。

但是,如果使用async, await關鍵字,則您的線程將不會等待存儲過程。 該線程將有資格工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM