广泛建议像这样使用ConfigureAwait(false)
:
await Do1Async().ConfigureAwait(false);
// ...
await Do2Async().ConfigureAwait(false);
// ...
await Do3Async().ConfigureAwait(false);
// ...
[IIRC,同时广泛不鼓励使用类似ContextSwitcher
的东西,它将异步执行流上下文切换到池线程,因此可能有助于避免在我的方法中出现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()
IIRC,它仍然比
await Task.Run(async () => { await Do1Async(); // ... await Do2Async(); // ... await Do3Async(); // ... });
选项要好,但是为什么呢?
最后,仍然有这种有趣的方法:ContextSwitcher
。
这里是An alternative to ConfigureAwait(false) everywhere中SynchronizationContextRemover
的相关部分:
the author's repo像这样删除同步上下文是否安全,在
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
广泛建议像这样使用ConfigureAwait(false):await Do1Async()。ConfigureAwait(false); // ...等待Do2Async()。ConfigureAwait(false); // ...等待Do3Async()。ConfigureAwait(false); // ...
[正如其他人指出的那样,对于现代代码,ContextSwitcher
的必要性降低了(特别是因为ASP.NET Core已成为主流)。此时是否在您的库中使用它是一个判断调用;就个人而言,我仍然使用它,但是我的主要异步库非常低级。