Application.ThreadException против AppDomain.UnhandledException - PullRequest
12 голосов
/ 24 мая 2011

Сначала немного предыстории: у меня есть многопоточное приложение WinForms, которое взаимодействует с нативными библиотеками.Это приложение иногда падает с необработанным исключением, и мы пытаемся выяснить, почему это происходит.Для этого я создаю глобальный обработчик исключений и планирую создать из него дамп-файл процесса.

Теперь возникает вопрос: на данный момент у этого приложения есть обработчик для Application.ThreadException, но он все еще падает с необработанным исключением.Я думаю о добавлении обработчика для AppDomain.UnhandledException также, хотя я не уверен, поможет ли он.Есть ли в этом сценарии возможное необработанное исключение, которое не будет поймано Application.ThreadException?

Ответы [ 3 ]

22 голосов
/ 24 мая 2011

Да, Application.ThreadException может перехватывать только те исключения, которые возникают в потоке пользовательского интерфейса. В коде, который запускается из-за уведомлений Windows. Или с технической точки зрения, события, которые запускаются циклом сообщений. Большинство событий Winforms соответствуют этой категории.

То, что он делает not trap, это исключения, возникающие в любом потоке, не являющемся пользовательским интерфейсом, например, рабочий поток, запущенный с Thread.Start (), ThreadPool.QueueUserWorkItem или метод BeginInvoke () делегата. Любое необработанное исключение в этих случаях прекратит работу приложения, AppDomain.UnhandledException - последний вздох.

Если пойти дальше, аппаратные исключения, которые возникают в неуправляемом потоке собственным кодом, который никогда не совершал управляемого вызова CLR, не могут быть обнаружены ни одним механизмом CLR. AccessViolation (код исключения 0xc0000005) является наиболее распространенной причиной смерти. Единственный способ перехватить их - через Windows API SetUnhandledExceptionFilter (). Это трудно понять правильно.

Вы можете отключить Application.ThreadException с помощью Application.SetUnhandledExceptionMode (). Что является мудрым решением, предоставление пользователю опции «Продолжить» не имеет большого смысла. Теперь все исключения в управляемых потоках ведут себя одинаково, используйте AppDomain.UnhandledException для их регистрации.

8 голосов
/ 24 мая 2011

Application.ThreadException будет вызываться только для необработанных исключений в потоках пользовательского интерфейса WinForms (см. здесь .). В этом случае может помочь добавление обработчика для AppDomain.UnhandledException (хотя и с некоторыми оговорками, как описано враздел замечаний здесь .)

3 голосов
/ 24 мая 2011

Я настоятельно рекомендую вам использовать генерацию минидампов ОС вместо своей.Это происходит по нескольким причинам:

  1. Создание минидампа из одного и того же процесса чрезвычайно проблематично и не всегда возможно.
  2. К моменту запуска ThreadException или UnhandledException,стек исключений уже размотан.Генерация минидампа в этой точке просто укажет вам на обработчик, а не на источник исключения.

Если ваше приложение находится в поле, используйте WER.Если вы проводите внутреннее тестирование, используйте ProcDump .Вы также можете просто скопировать файл мини-дамп, когда диалоговое окно «Отчет об ошибках» активно.

PS Существуют некоторые исключительные условия, особенно при выполнении p / Invoke, когда ни ThreadException, ни UnhandledException не будут работать.1017 *

PPS Если у вас есть сценарий отладки, попробуйте включить Managed Debugging Assistants , относящийся к p / Invoke.

...