Лучшая практика библиотеки Async: ConfigureAwait (false) и настройка контекста синхронизации
Хорошо известно, что в библиотеке общего назначения ConfigureAwait(false)
следует использовать для каждого вызова ожидания, чтобы избежать продолжения текущего SynchronizationContext.
В качестве альтернативы переполнению всей базы кода с помощью ConfigureAwait(false)
можно просто установить значение SynchronizationContext равным null один раз, методом общедоступной поверхности и восстановить его перед возвратом пользователю. Другими словами:
public async Task SomeSurfaceMethod()
{
var callerSyncCtx = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
try
{
// Do work
}
finally
{
SynchronizationContext.SetSynchronizationContext(callerSyncCtx);
}
}
Это также можно обернуть в using
для лучшей читаемости.
Есть ли недостаток этого подхода, не приводит ли он к такому же эффекту?
Основным преимуществом является, очевидно, читаемость - удаление всех вызовов ConfigureAwait(false)
. Это также может снизить вероятность того, что вы забудете ConfigureAwait(false)
где-нибудь (хотя анализаторы смягчают это, и можно утверждать, что разработчики могли бы также забыть об изменении SynchronizationContext).
Несколько экзотическое преимущество - это не включение выбора захвата SynchronizationContext или не во всех методах. Другими словами, в одном случае я могу запустить метод X с SynchronizationContext, в то время как в другом я могу запустить один и тот же метод без него. Когда ConfigureAwait(false)
внедряется везде, что невозможно. Конечно, это довольно редкое требование, но я столкнулся с ним во время работы над Npgsql (вызвав этот вопрос).
Ответы
Ответ 1
Как писал @MrinalKamboj в комментариях, здесь был предложен <временный параметр SynchronizationContext для null в методе общественной поверхности и отладки здесь. Кажется, что нет какой-либо конкретной проблемы, связанной с этим (см. Стивен Клири здесь).