Rya*_*yan 12 c# asp.net async-await
我有一个库,它公开了方法的同步和异步版本,但是在引擎盖下,它们都必须调用异步方法.我无法控制异步方法(它采用异步/等待和不不使用ConfigureAwait(false)),我也不能更换.
代码在ASP .NET请求的上下文中执行,所以为了避免死锁,这就是我所做的:
var capturedContext = SynchronizationContext.Current;
try
{
// Wipe the sync context, so that the bad library code won't find it
// That way, we avoid the deadlock
SynchronizationContext.SetSynchronizationContext(null);
// Call the async method and wait for the result
var task = MyMethodAsync();
task.Wait();
// Return the result
return task.Result;
}
finally
{
// Restore the sync context
SynchronizationContext.SetSynchronizationContext(capturedContext);
}
Run Code Online (Sandbox Code Playgroud)
这是否产生与MyMethodAsync在ConfigureAwait(false)其所有await上使用的效果相同的效果?我忽略了这种方法还有其他一些问题吗?
(MyMethodAsync完全没有意识到它是在ASP .NET上下文中运行的,它不会执行任何调用HttpContext.Current或类似的任何操作.它只是执行一些异步SQL调用,而编写器没有放置ConfigureAwait(false)任何这些调用)
如果您将此技术包装在适当命名的静态函数中,我认为您的建议明显优于Task.Run,即使仍然是两害相权取其轻。
Task.Run有很多问题:
SetSynchronizationContext多次使用并没有坏处)。Task.Run现在正在引入异步阻塞,而SetSynchronizationContext除了通过不恢复上下文而进行的优化之外,不会给您带来任何成本不断地。我也理解,鉴于应不惜一切代价避免阻塞异步代码,因此对于提出任何建议都会犹豫不决,但是您已经明确表示您已经意识到这一点,这是为了修复您直接控制范围之外的已知情况。我认为对这个主题的教条态度正在损害 .NET 生态系统。
我有一个库,它公开了方法的同步和异步版本,但是在引擎盖下,它们都必须调用异步方法.
公开同步版本库是错误的.只是假装同步API不存在.
所以要避免死锁
如果调用使用async/ 的异步方法,则死锁应该没有任何问题await.如果它不使用ConfigureAwait(false),那么它就没有那么高效,就是这样.死锁ConfigureAwait(false)仅适用于您尝试执行异步同步时(即,如果您从该库调用同步API).
因此,最简单和最简单的解决方案是忽略同步API,这些API设计不正确:
return await MyMethodAsync();
Run Code Online (Sandbox Code Playgroud)