Обработка исключений событий в Framework - PullRequest
0 голосов
/ 27 июля 2011

Я ищу некоторые рекомендации по передовым методам обработки исключений в событиях. В настоящее время, когда в моем приложении создаются исключения, во всплывающем диалоговом окне отображается сообщение об исключении, а затем приложение перезапускается после нажатия ОК. Проблема, которую я вижу, заключается в том, что в обработчиках событий некоторых сторонних библиотек возникает много исключений, и эти исключения проглатываются и никогда не отображаются, поскольку они находятся в фоновом потоке. Вот несколько решений, о которых думали разные люди, и я хотел бы знать, что любой из них - лучший подход.

  1. Переадресация фонового потока в поток пользовательского интерфейса в каждом обработчике событий в приложении.
  2. Обернуть события в другом классе, который имеет попытку / перехватить каждый метод, который вызывает событие. Затем перехватчик перенаправит исключение в поток пользовательского интерфейса, если оно возникнет.
  3. Получите доступ к сторонним библиотекам и поместите try / catch вокруг места, где вызываются события, которые затем могут быть перенаправлены в основное приложение глобальным событием.

Ответы [ 3 ]

1 голос
/ 27 июля 2011

Давайте обсудим ваши варианты так, как вы их перечислили:

1) Пересылать фоновый поток в поток пользовательского интерфейса в каждом событии. обработчик в приложении.

Вы не должны и не можете! потому что:

  • Вы не можете притворяться, что это событие "которое может исходить от третьей стороны" запускает другой фоновый поток или таймер.
  • Весь смысл наличия фоновых тем не чтобы заморозить пользовательский интерфейс, вам придется бороться с пользовательским интерфейсом длинными кодами выполнения.

2) Обернуть события в другом классе, который имеет попытку / перехватить каждый метод, который вызывает событие. Затем перехватчик перенаправит исключение в поток пользовательского интерфейса, если оно возникнет.

  • Та же точка, что и предыдущая. вы не можете притворяться, что событие запускает другой поток ..

3) Получите доступ к сторонним библиотекам и поместите try / catch вокруг места, где вызываются события, которые затем могут быть перенаправлены в основное приложение глобальным событием.

На самом деле это плохой выбор. Вам не следует изменять этот код сторонних библиотек , даже если вы можете . потому что:

  • Вы не являетесь автором этих библиотек.
  • Всякий раз, когда вы хотите обновить версию библиотеки или даже изменить библиотеки, вы должны переписать там код ..

Так что тебе нужно делать? Ответ - это то, что вы сейчас делаете:
Всякий раз, когда выдается какое-либо исключение, зарегистрируйте исключение, перезапустите ваш процесс, и в какой-то момент вашего процесса отправьте зарегистрированные ошибки на вашу электронную почту, а затем начните их исправлять.

0 голосов
/ 27 июля 2011

Если вы перехватываете событие AppDomain.UnhandledException, то проблема не в том, что они могут перезванивать в фоновом потоке, а в том, что сторонняя библиотека явно проглатывает исключения, создаваемые обработчиками. Это библиотека с плохим поведением, но, поскольку вы пишете код обработчика событий, вы можете перехватить исключения в обработчике событий и принудительно закрыть приложение.

Поскольку стороннюю библиотеку нельзя остановить с помощью исключения, вы можете принудительно завершить поток, вызвав:

Thread.CurrentThread.Abort();

Thread.Abort() обычно считается плохой практикой, но здесь это немного менее опасно, поскольку вы прерываете себя и, следовательно, не будете вводить исключение в потенциально неприятные места (вы также знаете, что поток не находится в неуправляемом контекст, поэтому он сразу прекратит работу.) Это все еще неприятный хак, но стороннее приложение не дает вам большого выбора. Исключение ThreadAbortException нельзя «остановить», поэтому сторонний код завершит свой поток, как только достигнет конца своих обработчиков исключений (даже если они попытаются его проглотить). Если сторонняя библиотека действительно противна, она может вызывать много кода в своем catch или, наконец, блоках, даже используя грязные трюки, чтобы остаться в живых, как запуск других потоков, но это должно быть довольно злонамеренным, чтобы сделать это.

Чтобы получить понятное поведение сообщения об ошибке, вы можете перенаправить Исключение в ваш поток пользовательского интерфейса, используя SynchronizationContext или Dispatcher, чтобы вызвать отображение вашего обработчика исключений (самый простой способ - просто перебросить исключение; я рекомендую встроить его как InnerException, так что вы не потеряете трассировку стека.)

Если вы действительно не доверяете библиотеке (и не хотите давать ей возможность остаться в живых даже через ее перехват и блоки наконец), вы можете явно выполнить маршалинг потока пользовательского интерфейса с помощью блокирующего вызова (для отображения вашего сообщения об ошибке) по-дружески), а затем позвоните Environment.FailFast(), чтобы убить ваш процесс. Это особенно жесткий способ завершить работу (он не будет вызывать никакого кода очистки и буквально прерывает процесс как можно быстрее), но он сводит к минимуму возможность любых потенциально вредных побочных эффектов, если состояние приложения стало очень поврежденным. Здесь можно следить за тем, чтобы поток пользовательского интерфейса мог быть заблокирован каким-либо другим вызовом пользовательского интерфейса, связанным со сторонним кодом. Если это произойдет, приложение будет заблокировано. Опять же, это было бы довольно злонамеренно, так что вы, вероятно, можете игнорировать это.

0 голосов
/ 27 июля 2011

Ничего из вышеперечисленного.Вместо этого подключите события к Application и AppDomain для необработанных исключений.

ДалееИнформация: Глобальное событие обработки исключений для приложений WPF Application.DispatcherUnhandledException запускается только для исключений, генерируемых в главном потоке пользовательского интерфейса .Однако AppDomain.CurrentDomain.UnhandledException должен запускаться для любого необработанного исключения в любом потоке (к сожалению, нет никаких препятствий для закрытия приложения после того, как оно достигло его здесь).

Провел некоторое быстрое исследование лучшихпрактики и обнаружили, что рекомендуется вручную обрабатывать исключения в фоновых потоках с блоком try\catch.Прочитайте раздел об исключениях на этой странице http://www.albahari.com/threading/, а также взгляните на этот вопрос StackOverflow Перехват необработанного исключения в отдельных потоках

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...