【发布时间】:2020-03-24 14:08:34
【问题描述】:
广泛推荐像这样使用ConfigureAwait(false):
await Do1Async().ConfigureAwait(false);
// ...
await Do2Async().ConfigureAwait(false);
// ...
await Do3Async().ConfigureAwait(false);
// ...
IIRC,同时广泛不鼓励使用类似ContextSwitcher 的东西,它将异步执行流上下文切换到池线程,因此可能有助于避免ConfigureAwait 在我的方法中的侵扰:
await ContextSwitcher.SwitchToThreadPool(); // this was even removed from async CTP
await Do1Async();
// ...
await Do2Async();
// ...
await Do3Async();
// ...
为什么第一个选项被认为是一个好的做法而这个不是,特别是考虑到await Do1Async().ConfigureAwait(false) 之后的代码将在与await ContextSwitcher.SwitchToThreadPool() 之后的代码完全相同的条件下继续运行?
另外,还有另一种选择:
await Task.Run(async () => {
await Do1Async();
// ...
await Do2Async();
// ...
await Do3Async();
// ...
});
IIRC,这仍然比 ContextSwitcher 选项好,但为什么呢?
最后还是有这个有趣的方法:An alternative to ConfigureAwait(false) everywhere。
这是来自the author's repo的SynchronizationContextRemover的相关部分:
public void OnCompleted(Action continuation)
{
var prevContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
continuation();
}
finally
{
SynchronizationContext.SetSynchronizationContext(prevContext);
}
}
像这样删除同步上下文是否安全,AFAIU 会在await new SynchronizationContextRemover() 之后影响整个同步范围?
await new SynchronizationContextRemover();
// we are still on the same thread
// but the synchronization context has been removed,
// be careful...
// ...
await Do1Async();
// ...until now
这个SynchronizationContextRemover 比ContextSwitcher 好多少,而且它可能少了一个池线程的切换?
【问题讨论】:
-
“广泛鼓励”的声明可能太强了 - stackoverflow.com/questions/13489065/…... 从来没有完全鼓励过,除非在作者知道他们不需要上下文的库代码中......甚至在 Core 中不太有用...
-
这些问题对于 ASP.NET Core 不再重要(那里没有同步上下文),但对 UI 应用程序可能仍然有效。我个人 stopped using
ConfigureAwait(false)even in my libraries 并在我的前端代码中使用了await Task.Run(async () => { ... })选项,我可能会从减少上下文切换的数量中受益。 -
老实说,我不认为
SwitchToThreadPool或类似@avo 有什么问题。 .NET 有一个 open issue to addThreadPool.Yieldawaitable,由 David Fowler 本人撰写,Stephen Toub's comment。另请检查this issue。不久前我也问过similar question。 -
@noseratio 谢谢,该线程中有很多很好的信息,看起来 .NET 团队将在 .NET 5.0 中添加
ThreadPool.SwitchTo()awaitable!也许你应该把它作为答案? -
仅供参考,Stephen Toub 刚刚发布了 ConfigureAwait FAQ,这是必读的。
标签: c# .net .net-core async-await task-parallel-library