Application.ThreadException vs AppDomain.UnhandledException
Сначала немного фона: у меня есть многопоточное приложение WinForms, которое делает interop для родных dll. Это приложение иногда срабатывает с необработанным исключением, и мы пытаемся выяснить, почему это происходит. Чтобы облегчить это, я создаю глобальный обработчик исключений, и я планирую сгенерировать из него файл процесса dumpfile.
Теперь на вопрос: на данный момент у этого приложения есть обработчик для Application.ThreadException
, но он по-прежнему падает с необработанным исключением. Я думаю о добавлении обработчика для AppDomain.UnhandledException
, хотя я не уверен, что он поможет. Есть ли возможное необработанное исключение в этом сценарии, которое не будет улавливаться Application.ThreadException
?
Ответы
Ответ 1
Да, Application.ThreadException может захватывать только исключения, возникающие в потоке пользовательского интерфейса. В коде, который запускается из-за уведомлений Windows. Или в технических терминах, события, вызванные контуром сообщения. Большинство событий Winforms соответствуют этой категории.
То, что это не ловушка, - это исключения, возникающие в любом потоке, отличном от UI, например, рабочий поток, запущенный с Thread.Start(), ThreadPool.QueueUserWorkItem или метод BeginInvoke() делегата. Любое необработанное исключение в этих случаях прекратит приложение, AppDomain.UnhandledException - последний вздох.
Идя дальше вниз, аппаратные исключения, которые возникают в неуправляемом потоке с помощью собственного кода, который никогда не вызывал никакого управляемого вызова CLR, не могут быть обнаружены с помощью какого-либо механизма CLR. AccessViolation (код исключения 0xc0000005) является наиболее распространенной причиной смерти. Единственный способ уловить их - через API Windows, SetUnhandledExceptionFilter(). Это трудно понять.
Вы можете отключить Application.ThreadException с Application.SetUnhandledExceptionMode(). Который разумно делать, предоставляя пользователю параметр "Продолжить", не имеет большого смысла. Теперь все исключения в управляемых потоках ведут себя одинаково, используйте AppDomain.UnhandledException для их регистрации.
Ответ 2
Application.ThreadException
будет поднят только для необработанных исключений в потоках пользовательского интерфейса WinForms (см. здесь.) Добавление обработчика для AppDomain.UnhandledException
может помочь в этом случае (хотя и с некоторыми оговорками, как описано в разделе примечаний здесь.)
Ответ 3
Я настоятельно рекомендую вам использовать генерацию мини-дисков OS вместо своих собственных. Это происходит по нескольким причинам:
- Генерирование мини-накопителя из одного и того же процесса крайне проблематично и не всегда возможно.
- К моменту запуска
ThreadException
или UnhandledException
стек исключений уже разворачивается. Генерирование minidump в этой точке просто укажет вам на обработчик, а не на источник исключения.
Если ваше приложение находится в поле, используйте WER. Если вы проводите внутреннее тестирование, используйте ProcDump. Вы также можете просто скопировать файл minidump, пока диалоговое окно отчета об ошибках активно.
P.S. Существуют некоторые исключительные условия - особенно при выполнении p/Invoke - где не работают ThreadException
и UnhandledException
.
P.P.S. Если у вас есть сценарий отладки, попробуйте включить "Помощники по отладке" , относящиеся к p/Invoke.