是的,你可以。通過重置當前的SynchronizationContext。
在頂層異步方法做到這一點:
async Task TopLevelAsync()
{
var syncContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
try
{
// no need for ConfigureAwait(false)
await SubTask1Async();
await SubTask2Async();
}
finally
{
SynchronizationContext.SetSynchronizationContext(syncContext);
}
}
一旦我已經與.ConfigureAwait一個函數內部(假)當前的SynchronizationContext將是無效和我並不需要關心關於它的子函數調用。那是對的嗎?
不幸的是,事實並非如此。這是一個危險的假設。這裏是爲什麼:
// in a top-level async method..
await FooAsync().ConfigureAwait(false);
async Task FooAsync()
{
var result = await BarAsync().ConfigureAwait(false);
// we are inside the ConfigureAwait(false), or in the
// continuation after ConfigureAwait(false), so at this
// point the SynchronizationContext must be null, right?
// No it's not.
}
Task<bool> BarAsync()
{
return Task.FromResult(true);
}
從BarAsync
上面的例子中同步完成,這意味着背後的FooAsync
方法狀態機繼續立即的執行,而無需重新調度。如果沒有重新調度邏輯,ConfigureAwait(false)
不會記入帳戶,所以SynchronizationContext從不重置。
我不認爲這是可能的,而且我覺得用'真'作爲默認的'ConfigureAwait'是一個很大的錯誤,太多。 – dasblinkenlight
@dasblinkenlight,不同意默認值「錯誤」。當你異步調用方法時,「默認情況下」期望繼續將在相同的「上下文」中執行。 – Fabio
@Fabio據我所知,唯一真正重要的地方就是UI。在其他地方,你並不關心它,至少,你並不太在意同意降低性能和死鎖的可能性。 – dasblinkenlight