Одна из распространенных ловушек для разработчиков 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% тестовое покрытие по логическим путям в методе.