Глобально перехватывать исключения в приложении WPF?
у нас есть приложение WPF, где его части могут создавать исключения во время выполнения. Я хотел бы глобально поймать любое необработанное исключение и зарегистрировать их, но в противном случае продолжить выполнение программы, как будто ничего не произошло (вроде VB On Error Resume Next).
возможно ли это в C#? И если да, то где именно мне нужно поместить код обработки исключений?
В настоящее время я не вижу ни одной точки, где я мог бы обернуть try/catch вокруг и что бы поймать всех исключения, которые могут возникнуть. И даже тогда я бы оставил все, что было выполнено из-за улова. Или я думаю в ужасно неправильно здесь?
ETA: потому что многие люди ниже указали на это: приложение не предназначено для управления атомными электростанциями. Если он падает, это не так уж и важно, но случайные исключения, которые в основном связаны с пользовательским интерфейсом, являются помехой в контексте, где он будет использоваться. Были (и, вероятно, все еще есть) некоторые из них те и так как он использует плагин архитектуры и может быть расширен другими (также студенты в этом случае; так нет опытные разработчики, которые умеют писать полностью безошибочный код).
что касается исключений, которые попадаются: я регистрирую их в файл журнала, включая полную трассировку стека. В этом и был весь смысл этого упражнения. Просто чтобы противостоять тем людям, которые воспринимали мою аналогию с OERN VB слишком буквально.
Я знаю, что слепо игнорирование определенных классов ошибок опасно и может повредить мой экземпляр приложения. Как было сказано ранее, эта программа не является критически важной для всех. Никто в здравом уме не поставил бы на это выживание человеческой цивилизации. Это просто небольшой инструмент для тестирования определенных подходов к дизайну wrt. программная инженерия.
для немедленного использования приложения есть не так много вещей, которые могут случиться на исключение:
- нет обработки исключений – диалоговое окно ошибки и выход из приложения. Эксперимент должен быть повторен, хотя, вероятно, с другим субъектом. Никаких ошибок не было зарегистрировано, что очень жаль.
- общая обработка исключений-доброкачественная ошибка в ловушке, никакого вреда не причинено. Это должен быть общий случай, оцениваемый по всем ошибкам, которые мы видели во время разработки. Игнорирование такого рода ошибок не должно иметь немедленных последствий; основные структуры данных тестируются достаточно хорошо, чтобы они легко выживали этот.
- общая обработка исключений-серьезная ошибка в ловушке, возможно, сбой в более поздний момент. Такое бывает редко. Мы никогда не видели его до сих пор. Ошибка регистрируется в любом случае, и сбой может быть неизбежным. Так что это концептуально похоже на самый первый случай. За исключением того, что у нас есть трассировка стека. И в большинстве случаев пользователь даже не заметит.
что касается данных эксперимента, генерируемых программой: серьезная ошибка в худшем случае просто не вызовет никаких данных чтобы быть записаны. Едва заметные изменения, которые хоть немного изменят результат эксперимента, весьма маловероятны. И даже в том случае, если результаты кажутся сомнительными на ошибки; можно выбросить, что если это останеца.
подводя итог: Да, я считаю себя по-прежнему, по крайней мере, частично вменяемым, и я не считаю глобальную процедуру обработки исключений, которая оставляет программу запущенной, чтобы быть обязательно полностью злой. Как уже дважды говорилось, такое решение может быть принято действительны, в зависимости от приложения. В данном случае было принято обоснованное решение, а не полная и полная чушь. для любого другого приложения это решение может выглядеть по-другому. Примечание стороны: есть только один пользователь для этого приложения. Это не что-то вроде Windows или Office, который получает миллионы, где стоимость наличия пузырей исключений для пользователя вообще будет очень отличаться в первую очередь уже.
6 ответов:
использовать
Application.DispatcherUnhandledException Event. Смотрите этот вопрос для резюме (см. ответ Дрю Ноукса).имейте в виду, что все еще будут исключения, которые исключают успешное возобновление вашего приложения, например, после переполнения стека, исчерпания памяти или потери сетевого подключения при попытке сохранения в базе данных.
AppDomain.События unhandledexception событие
это событие предоставляет уведомление о неперехваченных исключениях. Это позволяет приложение для регистрации информации об исключении перед системой обработчик по умолчанию сообщает об исключении пользователю и завершает приложение.
public App() { AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); } static void MyHandler(object sender, UnhandledExceptionEventArgs args) { Exception e = (Exception) args.ExceptionObject; Console.WriteLine("MyHandler caught : " + e.Message); Console.WriteLine("Runtime terminating: {0}", args.IsTerminating); }если событие UnhandledException обрабатывается в приложении по умолчанию домен, он поднимается там для любого необработанного исключения в любом нитка, независимо от того, в каком домене приложения запущен поток. Если нить запущен в домене приложения, который имеет обработчик событий для UnhandledException, событие возникает в этом домене приложения. Если домен приложения домен приложения по умолчанию, и есть также обработчик событий в домене приложения по умолчанию событие возникает в обоих доменах приложения.
например, предположим, что поток запускается в домене приложения " AD1", вызывает метод в домене приложения "AD2", а оттуда вызывает a метод в домене приложения "AD3", где он выдает исключение. Этот первый домен приложения, в котором событие unhandledexception может быть поднят "AD1". Если домен приложения не дефолт домен приложения, событие также может быть вызвано по умолчанию домен приложения.
кроме того, что другие упоминали здесь, обратите внимание, что объединение
Application.DispatcherUnhandledException(и подобия) С<configuration> <runtime> <legacyUnhandledExceptionPolicy enabled="1" /> </runtime> </configuration>на
app.configпредотвратит ваше исключение вторичных потоков от завершения работы приложения.
пример кода с использованием NLog что будет ловить исключения, брошенные из все потоки в AppDomain С UI dispatcher thread и асинхронные функции:
приложение.код XAML.cs:
public partial class App : Application { private static Logger _logger = LogManager.GetCurrentClassLogger(); protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); SetupExceptionHandling(); } private void SetupExceptionHandling() { AppDomain.CurrentDomain.UnhandledException += (s, e) => LogUnhandledException((Exception)e.ExceptionObject, "AppDomain.CurrentDomain.UnhandledException"); DispatcherUnhandledException += (s, e) => LogUnhandledException(e.Exception, "Application.Current.DispatcherUnhandledException"); TaskScheduler.UnobservedTaskException += (s, e) => LogUnhandledException(e.Exception, "TaskScheduler.UnobservedTaskException"); } private void LogUnhandledException(Exception exception, string source) { string message = $"Unhandled exception ({source})"; try { System.Reflection.AssemblyName assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName(); message = string.Format("Unhandled exception in {0} v{1}", assemblyName.Name, assemblyName.Version); } catch (Exception ex) { _logger.Error(ex, "Exception in LogUnhandledException"); } finally { _logger.Error(exception, message); } }
вот полный пример использования
NLogusing NLog; using System; using System.Windows; namespace MyApp { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { private static Logger logger = LogManager.GetCurrentClassLogger(); public App() { var currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException += CurrentDomain_UnhandledException; } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var ex = (Exception)e.ExceptionObject; logger.Error("UnhandledException caught : " + ex.Message); logger.Error("UnhandledException StackTrace : " + ex.StackTrace); logger.Fatal("Runtime terminating: {0}", e.IsTerminating); } } }
Как " VB на ошибку возобновить дальше?- Это звучит немного пугающе. Первая рекомендация-не делайте этого. Вторая рекомендация-не делайте этого и не думайте об этом. Вам нужно лучше изолировать свои недостатки. О том, как подойти к этой проблеме, это зависит от того, как Вы код структурирован. Если вы используете шаблон, такой как MVC или тому подобное, то это не должно быть слишком сложно и определенно не потребует глобального проглатывания исключений. Во-вторых, ищите хорошую библиотеку журналов, такую как log4net или используйте трассировку. Нам нужно знать больше деталей, например, о каких исключениях вы говорите, и какие части вашего приложения могут привести к возникновению исключений.
Comments