如果同时使用AppDomain.UnhandledException和Application.Dis

2019-06-23 11:30发布

阅读一些优秀的岗位约AppDomain.UnhandledException和Application.DispatcherUnhandledException之间的差额后,看来我应该都处理。 这是因为它是显著更容易,用户可以从主UI线程(即Application.DispatcherUnhandledException)抛出的异常中恢复。 正确?

同时,是否也应该给用户一个机会,继续为这两个计划,或只是Application.DispatcherUnhandledException?

下面的示例代码同时处理AppDomain.UnhandledException和Application.DispatcherUnhandledException,都给予用户尝试继续,尽管异常的选项。

[感谢和一些下面的代码是从其他的答案抬起]

App.xaml中

<Application x:Class="MyProgram.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Startup="App_StartupUriEventHandler"
         Exit="App_ExitEventHandler"
         DispatcherUnhandledException="AppUI_DispatcherUnhandledException">
    <Application.Resources>
    </Application.Resources>
</Application>

App.xaml.cs [删除]

/// <summary>
/// Add dispatcher for Appdomain.UnhandledException
/// </summary>
public App()
    : base()
{
    this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
}

/// <summary>
/// Catch unhandled exceptions thrown on the main UI thread and allow 
/// option for user to continue program. 
/// The OnDispatcherUnhandledException method below for AppDomain.UnhandledException will handle all other exceptions thrown by any thread.
/// </summary>
void AppUI_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
    if (e.Exception == null)
    {
        Application.Current.Shutdown();
        return;
    }
    string errorMessage = string.Format("An application error occurred. If this error occurs again there seems to be a serious bug 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);
    //insert code to log exception here
    if (MessageBox.Show(errorMessage, "Application User Interface 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();
        }
    }
    e.Handled = true;
}

/// <summary>
/// Catch unhandled exceptions not thrown by the main UI thread.
/// The above AppUI_DispatcherUnhandledException method for DispatcherUnhandledException will only handle exceptions thrown by the main UI thread. 
/// Unhandled exceptions caught by this method typically terminate the runtime.
/// </summary>
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
    string errorMessage = string.Format("An application error occurred. If this error occurs again there seems to be a serious bug 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);
    //insert code to log exception here
    if (MessageBox.Show(errorMessage, "Application UnhandledException 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();
        }
    }
    e.Handled = true;
}

Answer 1:

  • AppDomain.CurrentDomain.UnhandledException理论上捕获的应用程序域的所有线程的所有异常。 我发现这是非常不可靠的,虽然。
  • Application.Current.DispatcherUnhandledException捕捉UI线程上的所有异常。 这似乎能可靠地工作,并且将取代AppDomain.CurrentDomain.UnhandledException在UI线程处理器(优先)。 使用e.Handled = true ,以保持应用程序的运行。

  • 为了捕捉其他线程上的异常(在最好的情况下,他们是在自己的线程处理),我发现System.Threading.Tasks.Task(仅.NET 4.0及以上)要低维护。 在处理与任务的方法异常.ContinueWith(...,TaskContinuationOptions.OnlyOnFaulted) 见我的答案在这里了解详情。



Answer 2:

一个AppDomain.UnhandledException处理器是有线作为:

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

但我无法找到一个方法来标志作为处理程序处理 - 所以这似乎总是导致应用停机,不管你做什么。 因此,我不认为这是一个大量使用。

更好地处理Application.Current.DispatcherUnhandledException和测试CommunicationObjectFaultedException -因为你可以通过刚刚重新初始化代理恢复-正是因为你没有在初始连接。 例如:

void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {
    if (e.Exception is CommunicationObjectFaultedException) { //|| e.Exception is InvalidOperationException) {
        Reconnect();
        e.Handled = true;
    }
    else {
        MessageBox.Show(string.Format("An unexpected error has occured:\n{0}.\nThe application will close.", e.Exception));
        Application.Current.Shutdown();
    }
}

public bool Reconnect() {
    bool ok = false;
    MessageBoxResult result = MessageBox.Show("The connection to the server has been lost.  Try to reconnect?", "Connection lost", MessageBoxButton.YesNo);
    if (result == MessageBoxResult.Yes)
        ok = Initialize();
    if (!ok)
        Application.Current.Shutdown();
}

其中初始化有您最初的代理实例/连接代码。

在你的代码张贴以上我怀疑你正在处理DispatcherUnhandledException 两次 -在XAML和代码中布线的处理程序。



文章来源: Should use both AppDomain.UnhandledException and Application.DispatcherUnhandledException?