默認情況下,單元測試不捕獲在其運行的SynchronizationContext
,所以如果你寫的東西,如:爲什麼ConfigureAwait(true)在單元測試中不起作用?
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do();
WriteThread();
}
private Task Do()
{
return Task.Run(() =>
{
WriteThread();
Thread.Sleep(50);
});
}
private void WriteThread()
{
Debug.WriteLine($"CURRENT THREAD: {Thread.CurrentThread.ManagedThreadId}");
}
你獲得如下輸出:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 6
這是很正常的:一旦await
被調用並返回,流程不會返回到原始線程。現在
,如果我寫的測試方法是這樣的:
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do().ConfigureAwait(true); // <-- note this change
WriteThread();
}
我希望:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 8 // <-- back to the main Thread
相反,我得到的第一個測試的結果相同。
爲什麼不將執行編組回到測試方法的主線程?
'ConfigureAwait'與線程無關。一點都沒有。任何線程都可以執行任何任務。異步代碼可以在任何線程上的「await」後重新開始,始終如此。這是迄今爲止「Task」API的頭號誤解。我不知道它來自哪裏。 –
@BenjaminHodgson:我不同意你的描述。確實,作爲一個抽象,「SynchronizationContext」並不一定必須完全對應於線程。但是,這並不意味着它與他們完全沒有任何關係。在Winforms或WPF的常見情況下,上下文實際上與特定的線程綁定,「await」_will_實際上總是在該線程上恢復(除非另有指示),並且事實上可以考慮線程代碼正在執行。也許這種「誤解」來自它並不是真正的一個。 –