Исключение 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 7

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);
}