欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

[WPF 学习] 4.未处理异常的处理

程序员文章站 2022-05-18 10:37:40
异常不可避免,所有地方都写try...catch也麻烦,所以有了未处理异常的处理的东东,分别为以下三个事件: 1. Application.Current.DispatcherUnhandledException:DispatcherUnhandledException is raised by a ......

异常不可避免,所有地方都写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));
        }
    }
}