2016-03-15 41 views
1

試想一個sitution當主叫用戶創建一個任務:Task :: ConfigureAwait - 競賽條件?

{ 
var tWithCapturedCtx = Task.Run(...); 
var tWithoutCapturedCtx = tWithCapturedCtx.ConfigureAwait(false); 

await tWithoutCapturedCtx; 
} 

有沒有一種可能性,即tWithCapturedCtx將執行如此之快,將繼續對所捕獲的上下文中執行?

+2

您的編輯完全改變了問題,並可能使現有/接受的答案失效。請避免此類修改 - 如果您覺得您沒有正確表達您的問題,請隨時提出新問題。考慮恢復更改。 –

+0

@ user3284063:我回滾了你的編輯,因爲它提出了一個不同的問題。請隨時發佈一個新問題。 –

回答

1

tWithCapturedCtx是否有可能執行得如此之快以至於繼續將在捕獲的上下文中執行?

的排序。

如果tWithCapturedCtx在評估await時已經完成(這意味着tWithoutCapturedCtx也已完成),則根本沒有延續。 async方法只是繼續同步執行(在相同的上下文中)。

然而,如果tWithCapturedCtx尚未由await被評估的時間完成(這意味着tWithoutCapturedCtx也不是已經完成),則繼續被調度而不上下文被捕獲。

await檢查其等待時間是否完成以及await是否安排繼續時,還有另一個甚至更小的競態條件。如果在該窗口內等候完成,則繼續只是同步運行(同樣,在同一個上下文中)。

總之,ConfigureAwait(false)的意思是「我不在乎這個方法的其餘部分在什麼情況下運行」;它確實是而不是的意思是「在線程池中運行此方法的其餘部分」。如果您想說「在線程池線程上運行此其他代碼」,請使用Task.Run

+0

好的,謝謝。另一個問題:爲什麼他們不把continueOnCapturedContext參數放入Task :: Run方法的簽名中?這樣一來,最初的任務就可以用精確的知識來完成。 – user3284063

+0

@ user3284063:因爲這不是任務的責任。只有*調用*代碼知道它是否需要在捕獲的上下文中恢復。它是「配置等待」,而不是「配置任務」。 –

+0

@StephenCleary側注:OP編輯了我認爲重大改變了這個問題的問題 - 請檢查一下,看看是否應該回滾編輯(或者您可能想更新答案,我認爲這會有點不對)。 –

0

ConfigureAwait正在被稱爲繼續之前,甚至被添加到任務。繼續被添加到被配置爲不捕獲上下文的對象,所以當繼續運行時不會捕獲上下文(這實際上是它存在的事情,它不會實現其記錄的目的,如果它沒有)。

+0

對不起,我不太清楚 - 請參閱更新後的問題 – user3284063