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线程异常

用法如下:

 static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//处理未捕获的异常,始终将异常传送到 ThreadException 处理程序
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//集中处理异常
//订阅ThreadException事件,处理UI线程异常,处理方法为handler1
Application.ThreadException += new ThreadExceptionEventHandler(handler1);
//订阅UnhandledException事件,处理非UI线程异常,处理方法为handler2
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(handler2); Application.Run(new MainForm());
} public static void handler1(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show("哎呀,好像出错了T_T");
Application.Exit();
} public static void handler2(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show("哎呀,好像出错了T_T");
Application.Exit();
}
}

特别说明:

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

关于C_Sharp集中处理异常的更多相关文章

  1. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  2. ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”

    在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...

  3. 记一次tomcat线程创建异常调优:unable to create new native thread

    测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...

  4. 使用JSONObject.fromObject的时候出现“There is a cycle in the hierarchy”异常 的解决办法

    在使用JSONObject.fromObject的时候,出现“There is a cycle in the hierarchy”异常.   意思是出现了死循环,也就是Model之间有循环包含关系: ...

  5. SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论

    异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...

  6. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  7. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  8. [C#] C# 知识回顾 - 学会使用异常

    学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...

  9. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

随机推荐

  1. Oracle CHAR,VARCHAR,VARCHAR2,nvarchar类型的区别与使用(转载)

    一 varchar,varchar2,nvarchar,nvarchar2 四个类型都属于变长字符类型, varchar和varchar2的区别在与后者把所有字符都占两字节,前者只对汉字和全角等字符占 ...

  2. mybatis什么时候需要声明jdbcType?

    经常会见到以下两种写法:1. #{bookId}2. #{bookId,jdbcType=INTEGER}一般情况下,两种写法都可以.它们都可以获取Dao层传递过来的参数.但是,当传入的参数为null ...

  3. leetcode 196. Delete Duplicate Emails

    # 慢,内连接delete p1 from Person p1, Person p2 where p1.Email=p2.Email and p1.Id>p2.Id delete from Pe ...

  4. c++ stl常用

    #include<iostream>#include<string>#include<vector>#include<list>#include< ...

  5. 27-x的y次方的后三位数

    题目内容: 输入描述 数据分n组,对于每组数据有两个正整数x和y(x的y次方必须大于100) 输出描述 对于每组输出,输出一个值,即x的y次方结果的最后三位数 提示:13的13次方为:30287510 ...

  6. discuz回贴通知插件实现-发送邮件

    通过discuz的sendmail()来发送邮件 //引入发送邮件的函数文件 include libfile('function/mail'); //设置收件人地址,标题,内容发送邮件 sendmai ...

  7. Maven 学习笔记(一) 基础环境搭建

    在Java的世界里,项目的管理与构建,有两大常用工具,一个是Maven,另一个是Gradle,当然,还有一个正在淡出的Ant.Maven 和 Gradle 都是非常出色的工具,排除个人喜好,用哪个工具 ...

  8. Spring整合Struts2框架的第二种方式(Action由Spring框架来创建)(推荐大家来使用的)

    1. spring整合struts的基本操作见我的博文:https://www.cnblogs.com/wyhluckdog/p/10140588.html,这里面将spring与struts2框架整 ...

  9. VC字符串处理整理

    场景: 1.在存储数据时有时接口需要合并字符串值,并以某些特殊字符来合并部分,到需要的时候再分割它.如一些数值,人名等. 2.C++有strtok,stringstream和find函数来实现分割.可 ...

  10. Linux objdump命令

    一.简介 objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具. 二.选项 http://my.oschina.net/alphajay/blog/7729 http://man. ...