Async上的Microsoft Azure .NET SDK同步

时间:2018-05-16 21:02:12

标签: asp.net .net azure asynchronous synchronizationcontext

我正在为我的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死锁的方法?如果没有,那么这种方法的目的是什么?

1 个答案:

答案 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)。