[WPF 学习] 4.未处理异常的处理
程序员文章站
2022-10-29 16:35:57
异常不可避免,所有地方都写try...catch也麻烦,所以有了未处理异常的处理的东东,分别为以下三个事件: 1. Application.Current.DispatcherUnhandledException:DispatcherUnhandledException is raised by a ......
异常不可避免,所有地方都写try...catch也麻烦,所以有了未处理异常的处理的东东,分别为以下三个事件:
- application.current.dispatcherunhandledexception:dispatcherunhandledexception is raised by an application for each exception that is unhandled by code running on the main ui thread.(ui线程中任何未处理的异常将触发该事件)
- system.threading.tasks.taskscheduler.unobservedtaskexception:occurs when a faulted task's unobserved exception is about to trigger exception escalation policy(出错的任务中未观察到的异常将触发该事件)。在task被垃圾回收的时候,析构函数检测到该task对象还有未被处理过的异常,会抛出这个异常并触发,所以感觉总是慢一拍。
- 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)); } } }