我正在为 ASP.NET 应用程序使用 Azure Blob Storage SDK Microsoft.WindowsAzure.Storage
。我见过一些同步方法调用异步方法。他们使用来自 Microsoft.WindowsAzure.Storage.Core.Util
的名为 RunWithoutSynchronizationContext
的辅助方法。
代码基本上是做类似的事情
SynchronizationContext current = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext((SynchronizationContext) null);
methodAsync().Wait();
}
finally
{
SynchronizationContext.SetSynchronizationContext(current);
}
我只是想知道这是否是一种避免 .NET Framework 阻塞异步代码时出现死锁的方法?如果不是,那么这个方法的目的是什么?
最佳答案
使用 .Net TPL 进行异步开发时,API 开发人员常见的陷阱之一是 deadlocks 。最常见的是,这是由 SDK 使用者以同步方式使用异步 SDK 引起的。
您可以使用ConfigureAwait(false)
来避免死锁。在等待任务之前调用此例程将导致它忽略 SynchronizationContext。
var temp = await methodAsync().ConfigureAwait(false);
但是,您需要在整个 SDK 中放置 ConfigureAwait(false)
调用,而且很容易忘记。
因此,关键是了解 SynchronizationContext
的工作原理。无论何时使用它,都会调用它的 Send 或 Post 方法。
因此,我们需要做的就是确保这些方法永远不会被调用:
public void Test_SomeActionNoDeadlock()
{
var context = new Mock<SynchronizationContext>
{
CallBase = true
};
SynchronizationContext.SetSynchronizationContext(context.Object);
try
{
context.Verify(m =>
m.Post(It.IsAny<SendOrPostCallback>(), It.IsAny<object>()), Times.Never);
context.Verify(m =>
m.Send(It.IsAny<SendOrPostCallback>(), It.IsAny<object>()), Times.Never);
}
finally
{
SynchronizationContext.SetSynchronizationContext(null);
}
}
现在我们有办法保证在整个 SDK 方法中使用了ConfigureAwait(false),只要我们通过方法中的逻辑路径获得 100% 的测试覆盖率即可。
关于asp.net - Microsoft Azure .NET SDK 异步同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50379836/