В чем причина (вероятно, недокументированных) случаев подавления исключений .NET?

Я пытаюсь понять критерий .NET, когда исключения .NET подавляются, проглатываются или проходят незамеченными, чтобы обнаруживать/подозревать/предотвращать/быть начеку о таких инцидентах.

В онлайн-статье MSDN «Класс таймера» о .NET Framework 4.5 говорится:

В .NET Framework версии 2.0 и более ранних версиях компонент Timer перехватывает и подавляет все исключения, создаваемые обработчиками событий для события Elapsed. Это поведение может быть изменено в будущих выпусках .NET Framework.

Хммм, а .NET 4.5 — это уже будущая версия по отношению к .NET 2.0?
Хотя это риторический вопрос, и меня не очень волнует конкретный случай, упомянутый в документации.

Что меня действительно волнует и что я хочу понять, так это:
Каковы критерии, принципы и обоснование, в соответствии с которыми подавляются исключения .NET?

Обновление (в ответ на ответ Евгения Рика):

Итак, вопрос в том, какой поток должен быть подвержен исключению am, выброшенному на такт таймера?

Цитируя статью MSDN "Обработка исключений (библиотека параллельных задач)" :

Если вы не ждете задачу, которая распространяет исключение, или не обращаетесь к ее свойству Exception, исключение эскалируется в соответствии с политикой исключений .NET при сборке мусора.

(Забавная "политика исключений .NET", которую я нигде не мог найти...)

Что ж, меня интересует приложение WPF, которое, как я понимаю, является STA и имеет один основной родительский поток.
Я хочу, чтобы оно вылетало, если какое-либо исключение не было обработано.

Update2 (в ответ на комментарий Мэтта Смита):

Да, я знаю. Ссылаясь на <ThrowUnobservedTaskExceptions> Element:

Если исключение, связанное с Задачей, не наблюдалось, нет операции ожидания, родитель не присоединен и свойство TaskException не было прочитано, исключение задачи считается ненаблюдаемым.

В .NET Framework 4 по умолчанию, если задача, имеющая ненаблюдаемое исключение, подвергается сборке мусора, финализатор выдает исключение и завершает процесс. Окончание процесса определяется временем сборки мусора и финализации.

Чтобы упростить разработчикам написание асинхронного кода на основе задач, .NET Framework 4.5 изменяет это поведение по умолчанию для ненаблюдаемых исключений. Ненаблюдаемые исключения по-прежнему вызывают событие UnobservedTaskException, но по умолчанию процесс не завершается. Вместо этого исключение игнорируется после возникновения события, независимо от того, наблюдает ли обработчик событий исключение.

В .NET Framework 4.5 вы можете использовать этот элемент в файле конфигурации приложения, чтобы активировать поведение .NET Framework 4 по созданию исключения.

Я просто пропустил это, чтобы не раздувать вопрос и не получить ссылку на объяснение от Стивен Туб "Обработка исключений задач в .NET 4.5"

Вопрос в том, чтобы (очень хотел начать с этого вопроса) убедиться для меня:


person Gennady Vanin Геннадий Вани&    schedule 19.05.2013    source источник
comment
В .net 4.5 упомянутые вами незамеченные исключения Task проглатываются молча (по умолчанию — вы можете изменить это). В .net 4.0 поведение заключается в завершении приложения.   -  person Matt Smith    schedule 20.05.2013


Ответы (2)


Вот ссылка на политику (она была изменена в .net 2.0) и с тех пор остается неизменной: http://msdn.microsoft.com/en-us/library/ms228965.aspx

person Matt Smith    schedule 21.05.2013

Скорее всего, это просто проблема реализации:

  • Такты таймера запускаются в потоке пула потоков
  • Сам таймер не принадлежит потоку
  • Поток, создавший таймер, может больше не работать (или существовать)

Итак, вопрос в том, какой поток должен быть подвержен исключению am, выброшенному на такт таймера? На этот вопрос нет простого ответа, поэтому простое подавление исключения (т. е. запуск каждого тика с подразумеваемым try ... catch вокруг него) — это способ обойти этот вопрос.

person Eugen Rieck    schedule 19.05.2013
comment
Какой поток должен быть подвержен исключению am, вызванному таймером? IMO, его следует распространить на основной поток приложения и привести к сбою приложения, если оно не было обработано. - person Gennady Vanin Геннадий Вани&; 19.05.2013
comment
Ваше мнение кажется логичным при первом прочтении, но случай, когда таймер создается потоком, а затем больше не работает, когда таймер дает осечку, является чем-то вроде PITA: мы должны уведомить создателя таймер, но мы не можем. - person Eugen Rieck; 19.05.2013
comment
По этой логике любое исключение, вызванное дочерним процессом, порожденным потоком ThreadPool (или задачей), подавляется, поскольку его потоки используются повторно, и мы не знаем, кто создатель, чтобы уведомить его? По той же логике мы не сможем закрыть такие дочерние процессы при закрытии приложения. Но это не так - person Gennady Vanin Геннадий Вани&; 23.05.2013