Глобальный обработчик исключений WPF [дубликат]
этот вопрос уже есть ответ здесь:
иногда, при не воспроизводимых обстоятельствах, мое приложение WPF аварийно завершает работу без какого-либо сообщения. Приложение просто закрыть мгновенно.
где лучше всего реализовать глобальный Попробовать/catch блок. По крайней мере, я должен реализовать MessageBox с: "извините за неудобства ..."
9 ответов:
вы можете справиться с
AppDomain.UnhandledExceptionсобытиеEDIT: на самом деле, это событие, вероятно, более адекватно:
Application.DispatcherUnhandledException
вы можете ловить необработанные исключения на разных уровнях:
AppDomain.CurrentDomain.UnhandledExceptionиз всех потоков в AppDomain.Dispatcher.UnhandledExceptionиз одного конкретного потока диспетчера пользовательского интерфейса.Application.Current.DispatcherUnhandledExceptionС главная поток диспетчера пользовательского интерфейса в вашем приложении WPF.TaskScheduler.UnobservedTaskExceptionиз каждого домена приложения, который использует планировщик задач для асинхронного оперативный.вы должны рассмотреть, на каком уровне вам нужно ловить необработанные исключения.
выбор между #2 и #3 зависит от того, используете ли вы более одного потока WPF. Это довольно необычная ситуация, и если вы не уверены, являетесь ли вы или нет, то скорее всего, вы не.
небольшой пример кода для приложения.Диспетчер.UnhandledException:
public App() { this.Dispatcher.UnhandledException += OnDispatcherUnhandledException; } void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message); MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error); e.Handled = true; }Я добавил этот код в приложение.код XAML.cs
Я использую следующий код в моих приложениях WPF, чтобы показать диалоговое окно "извините за неудобства" всякий раз, когда происходит необработанное исключение. Он показывает сообщение об исключении и спрашивает пользователя, хотят ли они закрыть приложение или игнорировать исключение и продолжить (последний случай удобен, когда происходят несмертельные исключения, и пользователь все еще может нормально продолжать использовать приложение).
В Приложение.xaml добавить обработчик событий запуска:
<Application .... Startup="Application_Startup">В Приложение.код XAML.cs-код добавить запуск функция обработчика событий, которая будет регистрировать глобальный обработчик событий приложения:
using System.Windows.Threading; private void Application_Startup(object sender, StartupEventArgs e) { // Global exception handling Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(AppDispatcherUnhandledException); } void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { \#if DEBUG // In debug mode do not custom-handle the exception, let Visual Studio handle it e.Handled = false; \#else ShowUnhandledException(e); \#endif } void ShowUnhandledException(DispatcherUnhandledExceptionEventArgs e) { e.Handled = true; string errorMessage = string.Format("An application error occurred.\nPlease check whether your data is correct and repeat the action. If this error occurs again there seems to be a more serious malfunction in the application, and you better close it.\n\nError: {0}\n\nDo you want to continue?\n(if you click Yes you will continue with your work, if you click No the application will close)", e.Exception.Message + (e.Exception.InnerException != null ? "\n" + e.Exception.InnerException.Message : null)); if (MessageBox.Show(errorMessage, "Application Error", MessageBoxButton.YesNoCancel, MessageBoxImage.Error) == MessageBoxResult.No) { if (MessageBox.Show("WARNING: The application will close. Any changes will not be saved!\nDo you really want to close it?", "Close the application!", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning) == MessageBoxResult.Yes) { Application.Current.Shutdown(); } }
лучший ответ, вероятно,https://stackoverflow.com/a/1472562/601990.
вот код, который показывает, как его использовать:
приложение.код XAML.cs
public sealed partial class App { protected override void OnStartup(StartupEventArgs e) { // setting up the Dependency Injection container var resolver = ResolverFactory.Get(); // getting the ILogger or ILog interface var logger = resolver.Resolve<ILogger>(); RegisterGlobalExceptionHandling(logger); // Bootstrapping Dependency Injection // injects ViewModel into MainWindow.xaml // remember to remove the StartupUri attribute in App.xaml var mainWindow = resolver.Resolve<Pages.MainWindow>(); mainWindow.Show(); } private void RegisterGlobalExceptionHandling(ILogger log) { // this is the line you really want AppDomain.CurrentDomain.UnhandledException += (sender, args) => CurrentDomainOnUnhandledException(args, log); // optional: hooking up some more handlers // remember that you need to hook up additional handlers when // logging from other dispatchers, shedulers, or applications Application.Dispatcher.UnhandledException += (sender, args) => DispatcherOnUnhandledException(args, log); Application.Current.DispatcherUnhandledException += (sender, args) => CurrentOnDispatcherUnhandledException(args, log); TaskScheduler.UnobservedTaskException += (sender, args) => TaskSchedulerOnUnobservedTaskException(args, log); } private static void TaskSchedulerOnUnobservedTaskException(UnobservedTaskExceptionEventArgs args, ILogger log) { log.Error(args.Exception, args.Exception.Message); args.SetObserved(); } private static void CurrentOnDispatcherUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log) { log.Error(args.Exception, args.Exception.Message); // args.Handled = true; } private static void DispatcherOnUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log) { log.Error(args.Exception, args.Exception.Message); // args.Handled = true; } private static void CurrentDomainOnUnhandledException(UnhandledExceptionEventArgs args, ILogger log) { var exception = args.ExceptionObject as Exception; var terminatingMessage = args.IsTerminating ? " The application is terminating." : string.Empty; var exceptionMessage = exception?.Message ?? "An unmanaged exception occured."; var message = string.Concat(exceptionMessage, terminatingMessage); log.Error(exception, message); } }
В дополнение к постам выше:
Application.Current.DispatcherUnhandledExceptionне будет ловить исключения, которые выбрасываются из другого потока, то основной поток. Вы должны обрабатывать эти исключения в своем фактическом потоке. Но если вы хотите обрабатывать их в своем глобальном обработчике исключений, вы можете передать его в основной поток:
System.Threading.Thread t = new System.Threading.Thread(() => { try { ... //this exception will not be catched by //Application.DispatcherUnhandledException throw new Exception("huh.."); ... } catch (Exception ex) { //But we can handle it in the throwing thread //and pass it to the main thread wehre Application. //DispatcherUnhandledException can handle it System.Windows.Application.Current.Dispatcher.Invoke( System.Windows.Threading.DispatcherPriority.Normal, new Action<Exception>((exc) => { throw new Exception("Exception from another Thread", exc); }), ex); } });
чтобы дополнить ответ Томаса,
Applicationкласс также имеетDispatcherUnhandledExceptionсобытие, которое можно обработать.
полное решение здесь
Это объясняется очень хорошо с примером кода. Однако будьте осторожны, чтобы он не закрыл приложение.Добавить строку Приложение.Текущий.Выключение(); чтобы изящно закрыть приложение.
Как уже упоминалось выше
приложение.Текущий.DispatcherUnhandledException не поймает исключения, которые выбрасываются из другого потока, а затем основного потока.
Это фактически зависит от того, как был создан поток
один случай, который не обрабатывается приложением.Текущий.DispatcherUnhandledException-это система.Окна.Формы.Таймер для какого приложения.ThreadException может использоваться для обработки этих если вы запускаете формы в других потоках чем основной поток вам нужно будет установить приложение.ThreadException от каждого такого потока
Comments