關於未捕獲異常的處理(WPF)

轉載自:http://www.cnblogs.com/chenxizhang/p/3280947.html

這一篇文章來談談對於WPF應用程序開發中的未捕獲異常的處理。

首先,我們當然是要求應用程序開發人員,儘可能地在程序可能出現異常的地方都去捕捉異常,使用try…catch的方式。但是總是有一些意外的情況可能會發生,這就導致會出現所謂的“未捕獲異常(UnhandledException)”。對於這一類異常,如果我們沒有一個合適的策略進行處理,則當其發生的時候,會給用戶帶來不太好的使用體驗。例如下面這樣

image

備註:這個截圖是在Windows 8上面做的,其他操作系統看到的界面可能略有不同。

用戶看到這個窗口的時候,其實一般只能點擊Close the prograrm按鈕。也就是說,這種情況下會導致用戶無法繼續使用這個程序,而且他們還得不到任何具體的消息:到底發生了什麼事情了?除非他們去查看Windows的事件日誌。(但一般的用戶是不太會這個操作的)

image

我們可以看到在Windows事件日誌中,會有兩個具體的事件。首先是一個.NET Runtime的事件

image

然後是一個Application Error的事件

image

通常來說,這樣的用戶體驗有值得改進的地方。我們雖然不能防止異常的產生,但是當意外發生的時候,我們應該要以更好地方式地通知到用戶,或者儘可能地不要影響用戶當前的操作。

 

在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拋出了。
        }
    }
}

運行的效果大致如下

image

 

對於非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的話,用意是使用早期版本的異常處理策略。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章