[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));
        }
    }
}
相关文章
相关标签/搜索