众所周知,在通用库中,每次await调用都应使用ConfigureAwait(false)
,以避免继续使用当前的SynchronizationContext。
作为使用ConfigureAwait(false)
加密整个代码库的替代方法,可以在公共表面方法中将SynchronizationContext设置为null一次,并在返回给用户之前将其恢复。换句话说:
public async Task SomeSurfaceMethod()
{
var callerSyncCtx = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
try
{
// Do work
}
finally
{
SynchronizationContext.SetSynchronizationContext(callerSyncCtx);
}
}
这也可以包含在using
中,以提高可读性。
这种方法是否有缺点,它最终不会产生相同的效果吗?
主要优势显然是可读性 - 删除所有ConfigureAwait(false)
个电话。它还可以降低忘记ConfigureAwait(false)
某处的可能性(尽管分析人员可以减轻这种情况,并且可以说开发人员也可以忘记更改SynchronizationContext)。
有点奇特的优点是没有嵌入在所有方法中捕获SynchronizationContext的选择。换句话说,在一种情况下,我可能想要使用SynchronizationContext运行方法X,而在另一种情况下,我可能想要运行相同的方法而没有一个。当ConfigureAwait(false)
被嵌入到无法实现的任何地方时。当然,这是一个非常罕见的要求,但我在处理Npgsql时遇到了这个问题(触发了这个问题)。
答案 0 :(得分:0)
正如@MrinalKamboj在评论中所写,已经提出了在公共表面方法和设置中暂时将SynchronizationContext设置为null的方法here。似乎没有任何与此相关的特定问题(请参阅Stephen Cleary's answer here)。