代码之家  ›  专栏  ›  技术社区  ›  johnny g

wpf和application.threadexception[重复]

  •  3
  • johnny g  · 技术社区  · 15 年前

    这个问题已经有了答案:

    有时,在不可重复的情况下,我的WPF应用程序崩溃而没有任何消息。应用程序只需立即关闭。

    哪里是实现全局try/catch块的最佳位置。至少我必须实现一个消息框:“抱歉给您带来不便…”

    0 回复  |  直到 9 年前
        1
  •  159
  •   Thomas Levesque    15 年前

    你可以处理 AppDomain.UnhandledException 事件

    编辑:实际上,这个活动可能更合适: Application.DispatcherUnhandledException

        2
  •  488
  •   heltonbiker    8 年前

    可以在不同级别捕获未处理的异常:

    1. AppDomain.CurrentDomain.UnhandledException 来自appdomain中的所有线程。
    2. Dispatcher.UnhandledException 从单个特定的UI调度器线程。
    3. Application.Current.DispatcherUnhandledException 主要的 wpf应用程序中的ui分派器线程。
    4. TaskScheduler.UnobservedTaskException 在每个使用任务调度程序进行异步操作的Appdomain中。

    您应该考虑在什么级别捕获未处理的异常。

    决定2和3取决于您是否使用了多个wpf线程。这是一个非常奇特的情况,如果你不确定你是不是,那么很可能你不是。

        3
  •  109
  •   Sergey    6 年前

    application.dispatcher.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);
        // OR whatever you want like logging etc. MessageBox it's just example
        // for quick debugging etc.
        e.Handled = true;
    }
    

    我在app.xaml.cs中添加了此代码

        4
  •  41
  •   Community CDub    9 年前

    每当发生未处理的异常时,我在wpf应用程序中使用以下代码来显示“抱歉给您带来不便”对话框。它显示异常消息,并询问用户是否想要关闭应用程序或忽略异常并继续(后者的情况在发生非致命异常时是方便的,用户仍然可以正常地继续使用应用程序)。

    在app.xaml中添加启动事件处理程序:

    <Application .... Startup="Application_Startup">
    

    在app.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();
        } 
    }
    
        5
  •  17
  •   Community CDub    8 年前

    最好的答案可能是 https://stackoverflow.com/a/1472562/601990 是的。

    下面是一些说明如何使用它的代码:

    代码文件

    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);
        }
    }
    
        6
  •  11
  •   Tobias Hoefer    12 年前

    除上述职位外:

    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);
            }
        });
    
        7
  •  3
  •   dustyburwell    15 年前

    为了补充托马斯的回答, Application 类也有 DispatcherUnhandledException 你能处理的事件。

        8
  •  3
  •   karpanai    10 年前

    一个完整的解决方案是 here

    用示例代码解释得很好。但是,请注意不要关闭应用程序。 application.current.shutdown(); 优雅地关闭应用程序。

        9
  •  2
  •   Jens    11 年前

    如上所述

    application.current.dispatcherunhandledexception将不捕获 从另一个线程(然后是主线程)引发的异常。

    这取决于线程是如何创建的

    application.current.dispatcherunhandledexception未处理的一个案例是system.windows.forms.timer,可以使用application.threadexception处理这些 如果在主线程以外的其他线程上运行窗体,则需要从每个此类线程设置application.threadexception