异常不可避免,所有地方都写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:应用程序域的未处理异常

第1、2个事件很好理解,在ui线程和任务线程throw new excepiton(“测试”)都能测试出来,第3个事件我是折腾好久才找到触发的地方——比如在1、2事件的方法中又发生了异常,所以也可以理解1、2事件都有参数和方法可以设置成已处理(e.handled=true、e.setobserved()),第3个事件一被触发,game over。

最后附上我的代码

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));
        }
    }
}