異常不可避免,所有地方都寫try...catch也麻煩,所以有了未處理異常的處理的東東,分別為以下三個事件: 1. Application.Current.DispatcherUnhandledException:DispatcherUnhandledException is raised by a ...
異常不可避免,所有地方都寫try...catch也麻煩,所以有了未處理異常的處理的東東,分別為以下三個事件:
- Application.Current.DispatcherUnhandledException:DispatcherUnhandledException is raised by an Application for each exception that is unhandled by code running on the main UI thread.(UI線程中任何未處理的異常將觸發該事件)
- System.Threading.Tasks.TaskScheduler.UnobservedTaskException:Occurs when a faulted task's unobserved exception is about to trigger exception escalation policy(出錯的任務中未觀察到的異常將觸發該事件)。在Task被垃圾回收的時候,析構函數檢測到該Task對象還有未被處理過的異常,會拋出這個異常並觸發,所以感覺總是慢一拍。
- AppDomain.CurrentDomain.UnhandledException:應用程式域的未處理異常
第1、2個事件很好理解,在UI線程和任務線程throw new Excepiton("測試")都能測試出來,第3個事件我是折騰好久才找到觸發的地方——比如在1、2事件的方法中又發生了異常,所以也可以理解1、2事件都有參數和方法可以設置成已處理(e.Handled=True、e.SetObserved()),第3個事件一被觸發,game over。
最後附上我的代碼
using System;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace L3_Exception
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
/// <summary>
/// 非主線程錯誤
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (Exception item in e.Exception.InnerExceptions)
{
sb.AppendLine($@"異常類型:{item.GetType()}
異常內容:{item.Message}
來自:{item.Source}
{item.StackTrace}");
}
e.SetObserved();
Restart("Task Exception", sb.ToString());
}
/// <summary>
/// App裡面的錯誤
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
StringBuilder sb = new StringBuilder();
try
{
Exception ex = e.ExceptionObject as Exception;
sb.AppendLine($@"異常類型:{ ex.GetType()}
異常內容:{ ex.Message}
內部異常內容:{ex?.InnerException?.Message}
來自:{ ex.Source}
{ ex.StackTrace}");
}
catch
{
sb.AppendLine("不可恢復的WPF窗體線程異常");
}
Restart("Domain Exception", sb.ToString());
}
/// <summary>
/// 主線程錯誤
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($@"異常類型:{ e.Exception.GetType()}
異常內容:{ e.Exception.Message}
內部異常內容:{e.Exception?.InnerException?.Message}
來自:{ e.Exception.Source}
{ e.Exception.StackTrace}");
e.Handled = true;
Restart("主線程異常", sb.ToString());
}
private static void Restart(string title, string content)
{
MessageBox.Show(content, title);
//Current.Dispatcher.Invoke(() => Current.Shutdown(-1));
}
}
}