[WPF 學習] 4.未處理異常的處理

異常不可避免,全部地方都寫try...catch也麻煩,因此有了未處理異常的處理的東東,分別爲如下三個事件:函數

  1. Application.Current.DispatcherUnhandledException:DispatcherUnhandledException is raised by an Application for each exception that is unhandled by code running on the main UI thread.(UI線程中任何未處理的異常將觸發該事件)
  2. System.Threading.Tasks.TaskScheduler.UnobservedTaskException:Occurs when a faulted task's unobserved exception is about to trigger exception escalation policy(出錯的任務中未觀察到的異常將觸發該事件)。在Task被垃圾回收的時候,析構函數檢測到該Task對象還有未被處理過的異常,會拋出這個異常並觸發,因此感受老是慢一拍。
  3. AppDomain.CurrentDomain.UnhandledException:應用程序域的未處理異常

第一、2個事件很好理解,在UI線程和任務線程throw new Excepiton("測試")都能測試出來,第3個事件我是折騰很久才找到觸發的地方——好比在一、2事件的方法中又發生了異常,因此也能夠理解一、2事件都有參數和方法能夠設置成已處理(e.Handled=True、e.SetObserved()),第3個事件一被觸發,game over。測試

最後附上個人代碼ui

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));
        }
    }
}
相關文章
相關標籤/搜索