Обработка исключений из методов async Task
Задача
Спроектировать код для успешного результата несложно, но структура кода не может считаться правильной, если в ней не обрабатываются потенциальные ошибки. К счастью, обработка исключений из методов
async Task реализуется прямолинейно.Решение
Исключения можно перехватывать конструкцией
try/catch, как для синхронного кода:async Task ThrowExceptionAsync()Исключения, выданные из методов
{
await Task.Delay(TimeSpan.FromSeconds(1));
throw new InvalidOperationException("Test");
}
async Task TestAsync()
{
try {
await ThrowExceptionAsync();
}
catch (InvalidOperationException) {…}
}
async Task, помещаются в возвращаемый объект Task. При использовании await с задачей, в которой произошёл отказ, первое исключение этой задачи выдаётся повторно. При этом исходная трассировка стека будет правильно сохранена.Это сделано для того, чтобы в простом сценарии использовался простой код. В большинстве случаев код должен распространять исключения из вызываемых асинхронных методов. Всё, что нужно сделать, — использовать
await с задачей, возвращённой из асинхронного метода, и это исключение будет распространяться естественным образом.Обработка исключений при ожидании группы задач рассматривалась тут.
Async Void
Что если имеется метод
async void и требуется обработать исключения, распространённые из этого метода.Хорошего решения не существует. Если возможно, измените метод так, чтобы он возвращал
Task вместо void. Если вам требуется использовать метод async void, рассмотрите возможность упаковки всего кода метода в блок try/catch.Существует и другой возможный способ. Когда метод
async void распространяет исключение, это исключение выдаётся в контексте SynchronizationContext, активном на момент начала выполнения метода async void. Если среда выполнения предоставляет SynchronizationContext, то обычно она предоставляет механизм обработки этих высокоуровневых исключений на глобальном уровне. Например, WPF предоставляет Application.DispatcherUnhandledException, а ASP.NET — UseExceptionHandler.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.