1.写在前面java
“异常意味着什么?”,想必不用对此作多余的解释,咱们有理由相信在任何状况下任何应用程序都有可能出现异常,若在程序中没有对异常进行处理,则操做系统会以粗暴的方式处理掉它(弹出错误提示框),在不少应用软件中均可以看到这样的提示框,无疑会影响用户的体验。因此,咱们彻底有必要对应用程序进行全方位的异常处理,尽量地覆盖全部可能出现的异常,而程序的异常处理自己是一个很是重要却极易被忽视的问题。windows
2.通常的异常处理方式app
无非就是try...catch...finally...的应用,把全部自认为可能出现异常的代码都用try块wrap起来,没错,这确实是一种彻底可行的方法,但却不是最合适的作法。缘由以下:函数
假如须要开发一个WinForm应用程序,首先生成项目时VS自动生成机器代码,而后编码人员进行编码,实现须要的功能,编码人员很是谨慎,因此他在本身编写的代码中添加了若干个异常处理块。。。不管怎么测试都没有出现未被捕获的异常,他很开心,但是有一天运行应用程序时仍是发生了异常,这是为何?答案是编码人员没错,VS生成的机器代码也没错,而是操做系统出错了,在加载该APP时可能遇到了Interruption,进而引起了异常(固然,只是举个例子)学习
咱们能够看到,若撇开系统异常以及RunTimeException不讲,编码人员作得很是好,这样的作法是值得咱们学习的,也必须养成这样的习惯。测试
3.对于通常异常处理的建议编码
在上面介绍的通常的异常处理方式中,咱们不得不须要关注代码臃肿的问题,try...catch...finally...无疑会占用很大篇幅,这个是能够避免的,能够把异常尽可能集中处理,推荐的作法是对下层的Exception直接throw出去(在函数定义时添上throws声明便可),在Main函数中统一处理(由于到这里就不能继续throw了,不然。。。)spa
其次在catch块处理异常时,咱们能够新建一个独立的ExceptionClass定义各类异常的处理方法,避免出现大量冗余代码操作系统
每一个线程都要对应一个异常处理方法,Main属于主线程,在自定义的子线程里应该使用独立的异常处理线程
4.集中式异常处理
上面的第一条建议只适合控制台应用程序,不存在复杂的人机交互,对于WinForm应用程序将再也不适用,那么在WinForm应用程序中怎样合理地处理异常?
C Sharp的Application.ThreadException为咱们提供了便利,用于处理UI线程异常,AppDomain.CurrentDomain.UnhandledException用于处理非UI线程异常
用法以下:
1 static class Program 2 { 3 /// <summary> 4 /// 应用程序的主入口点。 5 /// </summary> 6 [STAThread] 7 [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)] 8 static void Main() 9 { 10 Application.EnableVisualStyles(); 11 Application.SetCompatibleTextRenderingDefault(false); 12 //处理未捕获的异常,始终将异常传送到 ThreadException 处理程序 13 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 14 //集中处理异常 15 //订阅ThreadException事件,处理UI线程异常,处理方法为handler1 16 Application.ThreadException += new ThreadExceptionEventHandler(handler1); 17 //订阅UnhandledException事件,处理非UI线程异常,处理方法为handler2 18 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(handler2); 19 20 Application.Run(new MainForm()); 21 } 22 23 public static void handler1(object sender, ThreadExceptionEventArgs e) 24 { 25 MessageBox.Show("哎呀,好像出错了T_T"); 26 Application.Exit(); 27 } 28 29 public static void handler2(object sender, UnhandledExceptionEventArgs e) 30 { 31 MessageBox.Show("哎呀,好像出错了T_T"); 32 Application.Exit(); 33 } 34 }
特别说明:
1>请注意Main方法里各个语句的顺序,集中异常处理的相关代码必须放在Application.Run();语句以前,不然没有效果
2>以上代码都在program.cs中,由于程序入口Main在这里
3>若对这样的处理方式还存在疑问,能够查看官方文档以及例程序源码http://msdn.microsoft.com/zh-cn/library/system.windows.forms.application.setunhandledexceptionmode.aspx
5.最后的建议(请务必看看)
1>集中式异常处理并非万能的,不建议过度依赖这样的处理方式
2>集中式异常处理只是最后的一道防线,程序内部仍然应该添加尽量完善的异常处理
3>任何异常处理都应该包括两个部分,即A.记录异常信息(写入ErrorLog或者发送到做者邮箱等等)B.善后操做(退出APP或者其它补救处理)