1. 程式人生 > >WPF捕獲全局未處理異常

WPF捕獲全局未處理異常

system 用戶界面 startup blog log 未處理 eve -s ebo

  在WPF開發過程中我們一般都用try/catch塊來捕獲異常,但不是每個異常我們都能捕獲,程序總會出現一些意想不到情況,拋出一些未捕獲的異常,這時就要用到全局異常捕獲,即在程序的最外層加上捕獲未處理異常,以免程序奔潰,影響用戶體驗。  

  在WPF應用程序中,會有兩大類未處理異常:一類是在UI線程拋出來的,例如點擊了用戶界面上面的某個控件,然後執行某個代碼的時候,遇到了異常;另一類是非UI線程跑出來的,例如在一個多線程的程序裏面,工作線程的代碼遇到了異常。

對於UI線程的未處理異常,我們用Application.DispatcherUnhandledException事件來處理,對於非UI線程的未處理異常用

AppDomain.UnhandledException事件來處理,對於Task內未處理異常用TaskScheduler.UnobservedTaskException事件來處理;

下面看代碼:

 public App()
 {
    //首先註冊開始和退出事件
     this.Startup += new StartupEventHandler(App_Startup);
     this.Exit += new ExitEventHandler(App_Exit);
 }

啟動事件對應的方法:

     void App_Startup(object sender, StartupEventArgs e)
        {
            
//UI線程未捕獲異常處理事件 this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
        //Task線程內未捕獲異常處理事件
       TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
//非UI線程未捕獲異常處理事件 AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler( CurrentDomain_UnhandledException); }

退出事件對應的方法:

void App_Exit(object sender, ExitEventArgs e)
        {
            //程序退出時需要處理的業務
        }

具體對應的方法:

void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                e.Handled = true; //把 Handled 屬性設為true,表示磁異常已處理,程序可以繼續運行,不會強制退出      
                MessageBox.Show("捕獲未處理異常:" + e.Exception.Message);
            }
            catch (Exception ex)
            {
                //此時程序出現嚴重異常,將強制結束退出
                MessageBox.Show("程序發生致命錯誤,將終止,請聯系運營商!");
            }

        }

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
           StringBuilder sbEx = new StringBuilder();
           if (e.IsTerminating)
                {
                    sbEx.Append("程序發生致命錯誤,將終止,請聯系運營商!\n");
                }
                sbEx.Append("捕獲未處理異常:");
                if (e.ExceptionObject is Exception)
                {
                    sbEx.Append(((Exception)e.ExceptionObject).Message);
                }
                else
                {
                    sbEx.Append(e.ExceptionObject);
                }
                MessageBox.Show(sbEx.ToString());
                Loger.WriteErrorLog("捕獲未處理異常:" + e.ExceptionObject);
        }

void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            //task線程內未處理捕獲
            MessageBox.Show("捕獲線程內未處理異常:" + args.Exception.Message);
            Loger.WriteErrorLog("捕獲線程內未處理異常:" + args.Exception);
            args.SetObserved();//設置該異常已察覺(這樣後就不會引起程序崩潰)
        }    

WPF捕獲全局未處理異常