关于C_Sharp集中处理异常

1.写在前面

“异常意味着什么?”,想必不用对此做多余的解释,我们有理由相信在任何情况下任何应用程序都有可能出现异常,若在程序中没有对异常进行处理,则操作系统会以粗暴的方式处理掉它(弹出错误提示框),在很多应用软件中都可以看到这样的提示框,无疑会影响用户的体验。所以,我们完全有必要对应用程序进行全方位的异常处理,尽可能地覆盖所有可能出现的异常,而程序的异常处理本身是一个非常重要却极易被忽视的问题。

2.一般的异常处理方式

无非就是try...catch...finally...的应用,把所有自认为可能出现异常的代码都用try块wrap起来,没错,这确实是一种完全可行的方法,但却不是最合适的做法。原因如下:

假如需要开发一个WinForm应用程序,首先生成项目时VS自动生成机器代码,然后编码人员进行编码,实现需要的功能,编码人员非常谨慎,所以他在自己编写的代码中添加了若干个异常处理块。。。无论怎么测试都没有出现未被捕获的异常,他很开心,可是有一天运行应用程序时还是发生了异常,这是为什么?答案是编码人员没错,VS生成的机器代码也没错,而是操作系统出错了,在加载该APP时可能遇到了Interruption,进而引发了异常(当然,只是举个例子)

我们可以看到,若撇开系统异常以及RunTimeException不讲,编码人员做得非常好,这样的做法是值得我们学习的,也必须养成这样的习惯。

3.对于一般异常处理的建议

在上面介绍的一般的异常处理方式中,我们不得不需要关注代码臃肿的问题,try...catch...finally...无疑会占用很大篇幅,这个是可以避免的,可以把异常尽量集中处理,推荐的做法是对下层的Exception直接throw出去(在函数定义时添上throws声明即可),在Main函数中统一处理(因为到这里就不能继续throw了,否则。。。)

其次在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或者其它补救处理)

posted @ 2014-03-06 09:32  梦烬  阅读(1127)  评论(0编辑  收藏  举报