Исключение Timeoutexception, TaskCanceledException С#
Я новичок в C#, и я нахожу исключения немного запутанными... У меня есть веб-приложение со следующим кодом:
try
{
//do something
}
catch (TimeoutException t)
{
Console.WriteLine(t);
}
catch (TaskCanceledException tc)
{
Console.WriteLine(tc);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Когда я отлаживаю код, он выдает e Exception
, самый общий, и когда я навожу курсор на информацию об исключении, оказывается, что это TaskCanceledException
. Почему TaskCanceledException
Не пойман? Если бы исключение было TimeoutException
, поймало бы оно TimeoutException
или также поймало бы Exception
? Почему это так?
1 ответ:
При ловле
Exception
, Вы должны убедиться, что это точно исключение, которое выбрасывается. При использованииTask.Run
илиTask.Factory.Startnew
и, как правило, с исключением, которое выбрасывается изTask
(если только задача не ожидается с помощьюawait
ключевое слово), внешнее исключение, с которым вы имеете дело, - этоAggregateException
, потому что блокTask
может иметь дочерние задачи, которые также могут создавать исключения.Из Обработка Исключений (Параллельная Библиотека Задач):
Необработанные исключения, создаваемые запущенным пользовательским кодом внутри задачи распространяются обратно к соединяющему потоку, за исключением некоторые сценарии, описанные далее в этом разделе. Исключения распространяются при использовании одной из статических или экземпляров задачи.Ждать или Задача.Методы ожидания, и вы обрабатываете их, заключая вызов в заявлении try-catch. Если задача является родителем прикрепленного ребенка задачи, или если вы ожидаете несколько задач, то несколько исключения можно было и бросить. Чтобы распространить все исключения обратно на вызывающий поток, инфраструктура задач оборачивает их в Экземпляр AggregateException. Исключение AggregateException имеет Свойство InnerExceptions, которое можно перечислить для проверки всех исходные исключения, которые были брошены, и обрабатывать (или не обрабатывать) каждый один в отдельности. Даже если выбрасывается только одно исключение, оно все равно остается завернутый в исключение AggregateException.
Итак, чтобы справиться с этим, вы должны поймать
AggregateException
:try { //do something } catch (TimeoutException t) { Console.WriteLine(t); } catch (TaskCanceledException tc) { Console.WriteLine(tc); } catch (AggregateException ae) { // This may contain multiple exceptions, which you can iterate with a foreach foreach (var exception in ae.InnerExceptions) { Console.WriteLine(exception.Message); } } catch (Exception e) { Console.WriteLine(e); }