WPF全局异常处理程序

时间:2009-09-24 15:40:01

标签: c# .net wpf exception exception-handling

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

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

9 个答案:

答案 0 :(得分:476)

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

  1. AppDomain.CurrentDomain.UnhandledException来自AppDomain中的所有主题。
  2. Dispatcher.UnhandledException来自单个特定的UI调度程序线程。
  3. Application.Current.DispatcherUnhandledException来自WPF应用程序中的 UI调度程序线程。
  4. TaskScheduler.UnobservedTaskException来自每个AppDomain,它使用任务调度程序进行异步操作。
  5. 您应该考虑在非处理未处理的例外所需的级别。

    #2和#3之间的决定取决于您是否使用多个WPF线程。这是一个非常奇特的情况,如果你不确定自己是否存在,那么你最有可能不是。

答案 1 :(得分:154)

您可以处理AppDomain.UnhandledException事件

编辑:实际上,这个事件可能更充足:Application.DispatcherUnhandledException

答案 2 :(得分:106)

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

中添加了此代码

答案 3 :(得分:40)

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

在App.xaml中添加Startup事件处理程序:

<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();
    } 
}

答案 4 :(得分:14)

最佳答案可能是https://stackoverflow.com/a/1472562/601990

以下是一些显示如何使用它的代码:

<强> App.xaml.cs

App2

答案 5 :(得分:11)

除上述帖子外:

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);
        }
    });

答案 6 :(得分:3)

为了补充托马斯的答案,Application课程还有DispatcherUnhandledException个活动,你可以处理。

答案 7 :(得分:3)

完整的解决方案是here

使用示例代码解释得非常好。但是,请注意它不会关闭应用程序。添加行 Application.Current.Shutdown(); 优雅地关闭应用程序。

答案 8 :(得分:1)

如上所述

  

Application.Current.DispatcherUnhandledException将无法捕获   从另一个线程抛出的异常,然后是主线程。

实际取决于线程的创建方式

Application.Current.DispatcherUnhandledException未处理的一个案例是System.Windows.Forms.Timer,可以使用Application.ThreadException来处理这些 如果你在主线程以外的其他线程上运行Forms,你将需要从每个这样的线程设置Application.ThreadException