[英]Behavior of async await with new threads
我試圖了解async / await的精確行為,並且在我周圍纏繞時遇到了一些麻煩。
考慮這個例子:
public async void StartThread()
{
while(true){
SomeOtherClass.SomeSynchronousStuff();
var something = await SomeOtherClass.SomeOtherAsyncMethod();
}
}
public void ConstructorForThisClass()
{
Thread thread = new Thread(StartThread);
thread.Start();
}
我對async / await的理解是,幕后發生的事情是編譯器本質上是將代碼轉換成一堆回調並為每個回調存儲狀態對象。
所以根據這個,我的問題是:
SomeOtherAsyncMethod
,它是否會被釋放以用於其他工作? SomeOtherAsyncMethod
返回時,線程是否會簡單地結束並且線程池線程取代它? StartThread
函數? 新創建的線程是否會異步運行?
你的措辭有點問題。 線程的創建是完全同步的。
意思是,當線程正在等待SomeOtherAsyncMethod時,它是否會被釋放以用於其他工作?
您是使用Thread
類手動創建線程,而不是Threadpool線程。 它不在AppDomain中共享。 它會被釋放,一旦它擊中第一await
關鍵字,但因為你在一個無限使用它while
循環,它不會用於比其他任何其他工作。
如果前面的條件為真,那么當SomeOtherAsyncMethod返回時,線程是否會簡單地結束並且線程池線程取代它?
忽略前者,因為你不使用ConfigureAwait(false)
,所以繼續將在任意ThreadPool線程上運行。 但這實際上取決於背景。 由於您在新線程上運行此委托,所以會發生這種情況。 但是,如果你是從UI線程運行它,那么繼續嘗試通過相關的TaskScheduler
和相應的SynchronizationContext
將自身編組到UI消息循環中。
我如何在線程池線程而不是托管線程上發布StartThread函數?
Thread
類和ThreadPool
類啟動的所有線程都是托管線程。 如果你的意思是“如何在ThreadPool
Task.Run
運行此委托”,那么答案是通過Task.Run
或通過ThreadPool
靜態類。
當一個等待的方法返回其調用者時,它是否被強制在調用它的線程上恢復,或者任何空閑線程可以取代它?
如果在沒有ConfigureAwait(false)
情況下運行,它將被強制轉換為當前的TaskScheduler
及其底層的SynchronizationContext
。 這意味着如果你在UI消息循環中運行,並await
那里調用await
,它將嘗試將延續發布到它。 如果沒有可用的自定義TaskScheduler
,它將使用默認的一個,即線程池調度程序。
裸線程與async
/ await
不兼容。
新創建的線程是否會異步運行? 意思是,當線程正在等待SomeOtherAsyncMethod時,它是否會被釋放以用於其他工作?
實際上,線程將退出。 當StartThread
后恢復await
,它會執行一個線程池線程。
我如何在線程池線程而不是托管線程上發布StartThread函數?
首先,您需要將StartThread
的返回類型從void
更改為Task
。 async void
方法適用於事件處理程序; 在其他地方使用它們會導致各種各樣的問題。
然后你可以通過Task.Run
調用它:
var backgroundTask = Task.Run(() => StartThread());
當一個等待的方法返回其調用者時,它是否被強制在調用它的線程上恢復,或者任何空閑線程可以取代它?
默認情況下, await
運算符將捕獲“當前上下文”並在該上下文中繼續。 這個“當前上下文”是SynchronizationContext.Current
,除非它是null
,在這種情況下它是TaskScheduler.Current
。 通常,這是UI / ASP.NET SynchronizationContext
,否則它是線程池上下文( TaskScheduler.Default
)。
您可能會發現我的async
介紹很有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.