Общий подход к правильной обработке отмены задачи
Я делаю обзор кода, и меня беспокоит этот шаблон, видимый во всем этом коде:
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
так же легко.До тех пор, пока вы следуете рекомендациям по асинхронности (например, нет асинхронной синхронизации или синхронизации по асинхронности), вам не нужно беспокоиться об этом.