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

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


当前回答

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

其他回答

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

AppDomain. currentdomain . unhandledexception 调度员。从单个特定的UI分派器线程中UnhandledException。 来自WPF应用程序的主UI调度程序线程。 TaskScheduler。每个使用任务调度器进行异步操作的AppDomain内的UnobservedTaskException。

您应该考虑需要在哪个级别捕获未处理的异常。

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

您可以处理AppDomain。UnhandledException事件

编辑:实际上,这个事件可能更合适:应用程序。DispatcherUnhandledException

为了补充Thomas的回答,Application类还有可以处理的DispatcherUnhandledException事件。

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

除上述职位外:

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