WPF程序中,對於異常的捕獲一般使用try/catch塊。就像程序中的bug一樣,很難保證程序中所有的異常都能夠通過try/catch捕獲。如果異常沒有被捕獲,輕則影響用戶體驗,嚴重時會導致數據丟失。WPF中提供了Application.DispatcherUnhandledException事件和AppDomain.UnhandledException事件,通過注冊這兩個事件,我們可以對未經處理的全局異常集中執行自定義處理。
對於在主UI線程上運行的代碼未處理的每個異常,Application都將引發一個 DispatcherUnhandledException。當您處理一個來自 DispatcherUnhandledException 的未經處理的異常,並且不希望 WPF 繼續處理該異常時,需要將 Handled 屬性設置為 true。通俗的講,如果不希望應用程序崩潰,我們需要將Handled 屬性設置為 true。但不是所有的異常都可恢復,如果異常是FileNotFoundException,程序可以在處理異常后繼續運行,如果異常是StackOverflowException,則無法再繼續運行,即將關閉。
對於在任何線程中的任何未處理的異常,以及無論什么應用程序域中的異常都將引發UnhandledException。如果UI線程中的異常未處理,也會引發UnhandledException。從.NET Framework 4開始,損壞進程狀態異常將不引發該事件,如堆棧溢出,或者是訪問沖突。因為默認情況下,公共語言運行時 (CLR) 並不把這些異常輸出到托管代碼,且不為它們調用 try/catch 塊。
奉上簡單代碼:
1 /// <summary>
2 /// 應用程序啟動 3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 private void Application_Startup(object sender, StartupEventArgs e) 7 { 8 Current.DispatcherUnhandledException += App_OnDispatcherUnhandledException; 9 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 10 } 11
12 /// <summary>
13 /// UI線程拋出全局異常事件處理 14 /// </summary>
15 /// <param name="sender"></param>
16 /// <param name="e"></param>
17 private void App_OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) 18 { 19 try
20 { 21 LogHelper.Instance.Logger.Error(e.Exception, "UI線程全局異常"); 22 e.Handled = true; 23 } 24 catch (Exception ex) 25 { 26 LogHelper.Instance.Logger.Error(ex, "不可恢復的UI線程全局異常"); 27 MessageBox.Show("應用程序發生不可恢復的異常,將要退出!"); 28 } 29 } 30
31 /// <summary>
32 /// 非UI線程拋出全局異常事件處理 33 /// </summary>
34 /// <param name="sender"></param>
35 /// <param name="e"></param>
36 private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 37 { 38 try
39 { 40 var exception = e.ExceptionObject as Exception; 41 if (exception != null) 42 { 43 LogHelper.Instance.Logger.Error(exception, "非UI線程全局異常"); 44 } 45 } 46 catch (Exception ex) 47 { 48 LogHelper.Instance.Logger.Error(ex, "不可恢復的非UI線程全局異常"); 49 MessageBox.Show("應用程序發生不可恢復的異常,將要退出!"); 50 } 51 }