Синхронизация Microsoft Azure .NET SDK в Async - PullRequest
0 голосов
/ 17 мая 2018

Я использую Azure Blob Storage SDK Microsoft.WindowsAzure.Storage для своего приложения ASP.NET. Я видел какой-то синхронный метод, вызывающий асинхронный метод. Они используют вспомогательный метод с именем 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 голосов
/ 17 мая 2018

Одна из распространенных ловушек для разработчиков API в асинхронной разработке с .Net TPL составляет взаимоблокировки .Чаще всего это вызвано тем, что потребители SDK используют асинхронный SDK синхронно .

Вы можете использовать ConfigureAwait(false), чтобы избежать взаимоблокировки.Вызов этой подпрограммы перед ожиданием задачи заставит ее игнорировать SynchronizationContext.

var temp = await methodAsync().ConfigureAwait(false);

Однако вам нужно разместить ConfigureAwait(false) вызовов по всему SDK, и это легко забыть.

Итак, фокус в том, чтобы понять, как работает 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);
    }
}

Теперь у нас есть способ гарантировать, что ConfigureAwait (false) использовался на протяжении всегоМетод SDK , при условии, что мы получаем 100% тестовое покрытие по логическим путям в методе.

...