轉載自:http://www.cnblogs.com/chenxizhang/p/3280947.html
這一篇文章來談談對于WPF應用程序開發中的未捕獲異常的處理。
首先,我們當然是要求應用程序開發人員,盡可能地在程序可能出現異常的地方都去捕捉異常,使用try…catch的方式。但是總是有一些意外的情況可能會發生,這就導致會出現所謂的“未捕獲異常(UnhandledException)”。對于這一類異常,如果我們沒有一個合適的策略進行處理,則當其發生的時候,會給用戶帶來不太好的使用體驗。例如下面這樣
備注:這個截圖是在Windows 8上面做的,其他操作系統看到的界面可能略有不同。
用戶看到這個窗口的時候,其實一般只能點擊Close the prograrm按鈕。也就是說,這種情況下會導致用戶無法繼續使用這個程序,而且他們還得不到任何具體的消息:到底發生了什么事情了?除非他們去查看Windows的事件日志。(但一般的用戶是不太會這個操作的)
查看Windows的事件日志:https://jingyan.baidu.com/article/91f5db1b057fb61c7e05e375.html
我們可以看到在Windows事件日志中,會有兩個具體的事件。首先是一個.NET Runtime的事件
然后是一個Application Error的事件
通常來說,這樣的用戶體驗有值得改進的地方。我們雖然不能防止異常的產生,但是當意外發生的時候,我們應該要以更好地方式地通知到用戶,或者盡可能地不要影響用戶當前的操作。
?
在WPF這種應用程序中,會有兩大類未處理異常:一類是在UI線程拋出來的,例如點擊了用戶界面上面的某個控件,然后執行某個代碼的時候,遇到了異常;另一類是非UI線程跑出來的,例如在一個多線程的程序里面,工作線程的代碼遇到了異常。
對于UI線程的未處理異常,我們可以通過監控下面這個事件來處理
Application.Current.DispatcherUnhandledException???http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx
一個參考代碼如下:
using System;
using System.Windows;namespace WpfApplicationExceptionSample
{/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : Application{public App(){Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;}void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e){MessageBox.Show("我們很抱歉,當前應用程序遇到一些問題,該操作已經終止,請進行重試,如果問題繼續存在,請聯系管理員.", "意外的操作", MessageBoxButton.OK, MessageBoxImage.Information);//這里通常需要給用戶一些較為友好的提示,并且后續可能的操作e.Handled = true;//使用這一行代碼告訴運行時,該異常被處理了,不再作為UnhandledException拋出了。}}
}
運行的效果大致如下
?
對于非UI線程拋出的未處理異常,我們需要監控另外一個事件來處理
AppDomain.CurrentDomain.UnhandledException??http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx?
一個參考代碼如下
using System;
using System.Windows;namespace WpfApplicationExceptionSample
{/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : Application{public App(){AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;}void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e){MessageBox.Show("我們很抱歉,當前應用程序遇到一些問題,該操作已經終止,請進行重試,如果問題繼續存在,請聯系管理員.", "意外的操作", MessageBoxButton.OK, MessageBoxImage.Information);}}
}
?
令人不解的是,這個事件中沒有和前面那個事件一樣的e.Handled參數,就是說,雖然這樣是可以捕捉到非UI線程的異常,而且也可以進行相應的處理,但是應用程序還是會退出,也就是說這個異常還是被當作是未處理異常繼續匯報給Runtime。
為了改進這一點,我們可以通過修改配置文件來實現。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime><legacyUnhandledExceptionPolicy enabled="1"/></runtime><startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup>
</configuration>
?
這里的legacyUnhandledExceptionPolicy,如果enabled=1的話,用意是使用早期版本的異常處理策略。