Kyl*_*yle 32 c# wpf exception-handling uncaught-exception uncaughtexceptionhandler
在阅读了一些关于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>
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*chs 39
AppDomain.CurrentDomain.UnhandledException
理论上捕获appdomain的所有线程上的所有异常.但我发现这是非常不可靠的.Application.Current.DispatcherUnhandledException
捕获UI线程上的所有异常.这似乎可靠地工作,并将替换AppDomain.CurrentDomain.UnhandledException
UI线程上的处理程序(优先级).使用e.Handled = true
以保持应用程序的运行.
为了捕获其他线程上的异常(在最好的情况下,它们是在自己的线程上处理的),我发现System.Threading.Tasks.Task(仅限.NET 4.0及更高版本)是低维护的.使用该方法处理任务中的异常.ContinueWith(...,TaskContinuationOptions.OnlyOnFaulted)
.见我的答案在这里了解详情.
一个AppDomain.UnhandledException
处理器是有线作为:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Run Code Online (Sandbox Code Playgroud)
但我无法找到一种方法来标记处理程序中的处理 - 所以这似乎总会导致应用程序关闭,无论你做什么.所以我认为这不是很多用途.
更好地处理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();
}
Run Code Online (Sandbox Code Playgroud)
其中Initialize具有您的初始代理实例化/连接代码.
在您上面发布的代码中,我怀疑您正在处理DispatcherUnhandledException
两次 - 通过在xaml和代码中连接处理程序.