我正在为我的ASP.NET应用程序使用Azure Blob存储SDK Microsoft.WindowsAzure.Storage
。我见过一些调用异步方法的同步方法。他们使用RunWithoutSynchronizationContext
中名为Microsoft.WindowsAzure.Storage.Core.Util
的辅助方法。
代码基本上就像
一样 SynchronizationContext current = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext((SynchronizationContext) null);
methodAsync().Wait();
}
finally
{
SynchronizationContext.SetSynchronizationContext(current);
}
我只是想知道这是否是一种在阻止异步代码时避免.NET Framework死锁的方法?如果没有,那么这种方法的目的是什么?
答案 0 :(得分:0)
。strong 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);
}
}
现在,只要我们通过方法中的逻辑路径获得100%的测试覆盖率,我们就可以保证在整个SDK方法中使用了ConfigureAwait(false)。