Общий подход к правильной обработке отмены задачи
Я делаю обзор кода, и меня беспокоит этот шаблон, видимый во всем этом коде:
try
{
await DoSomethingAsync();
await DoSomethingElseAsync();
// and so on...
}
catch (OperationCanceledException)
{
// all good, user cancelled
// log and return
return;
}
// handle other particular exceptions
// ...
catch (Exception ex)
{
// fatal error, alert the user
FatalErrorMessage(ex);
}
Часть, о которой я беспокоюсь, - это обработка OperationCanceledException. Не должен ли этот код также обрабатывать AggregateException и проверять, является ли единственным внутренним исключением OperationCanceledException?
Я знаю, что Task.Wait или Task.Result бросят AggregateException так, а не OperationCanceledException. Автор кода заверил меня, что она использует только async/await наизнанку и никогда не использует Wait/Result. Таким образом, ей не нравится идея дополнительно наблюдение AggregateException за отменой. Однако моя точка зрения заключается в том, что некоторые стандартные API BCL на основе Task все еще могут быть обернуты OperationCanceledException с AggregateException, например, потому что они все еще могут обращаться к Task.Result внутри.
Есть ли в этом смысл? Должны ли мы беспокоиться о том, чтобы правильно обрабатывать как OperationCanceledException, так и AggregateException, Чтобы правильно наблюдать отмену?
2 ответа:
Ну, это определенно технически возможно, что очень легко проверить с помощью этого кода:
static void Main() { Test().Wait(); } static async Task Test() { try { await ThrowAggregate(); } catch (Exception e) { Console.WriteLine(e); } } static async Task ThrowAggregate() { ThrowException().Wait(); } static async Task ThrowException() { throw new OperationCanceledException(); }
ThrowAggregateсохраняет исключение AggregateException внутри возвращаемой задачи, поэтому ожидание его по-прежнему вызываетAggregateException. Так что, если вы хотите быть прилежным, вам тоже нужно пойматьAggregateException.Тем не менее, это очень маловероятно, что любой метод в BCL будет делать это, и если бы у вас были большие проблемы, чем обработка исключений, так как вы делаете асинхронную поверх синхронизации. Я бы больше беспокоился за тебя. собственный код.
Однако я хочу сказать, что некоторые стандартные API BCL, основанные на задачах, все еще могут обернуть OperationCanceledException с AggregateException, например, потому что они все еще могут обращаться к задаче.Результат внутренне.
Нет, они не сделают этого.
Я бы сказал, что нет. Конечно, возможно , чтоДолжны ли мы беспокоиться об обработке как OperationCanceledException, так и AggregateException, чтобы правильно наблюдать отмену?
AggregateExceptionможет содержатьOperationCanceledException, но он также может содержатьother particular exceptionsтак же легко.До тех пор, пока вы следуете рекомендациям по асинхронности (например, нет асинхронной синхронизации или синхронизации по асинхронности), вам не нужно беспокоиться об этом.