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. asp.net后台解析JSON,并将值赋给对象

    示例代码如下: using System; using System.Collections.Generic; using System.Web.Script.Serialization; publi ...

  2. Linux 线程调度

    1.线程sleep()后,会让出cpu的时间片,交由其他线程进行抢占cpu. 线程之间正常的切换是依靠时间片的. 当主线程没有结束,且其在所占有的时间片内,并没有结束自己的工作,此时,子线程将会抢占c ...

  3. C++ 输入cin 和输出cout

    C++输入cout与输出cin 输入和输出并不是C++语言中的正式组成成分.C和C++本身都没有为输入和输出提供专门的语句结构.输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的. ...

  4. dedecms的自定义模块

    dedecms的自定义模块   1.在dedecms主目录下创建一个模块目录 2.在模块目录下创建如下目录 网站根目录/ |-自定义模块 |-control 控制器 |-model 模型 |-stat ...

  5. 通过yiic来创建yii应用

    一.通过yiic来创建yii应用 (*yiic命令在yii下载包的framework目录下) 1.把你自已的php环境添加到系统环境变量中. 2.在命令行下输入: yiic webapp 位置\名称 ...

  6. Package gtk+-3.0 was not found in the pkg-config search path

    问题描述: 在fedora21系统上通过rpmbuild构建fcitx的二进制包时出现以上错误,经老程序员指点:“是相应的开发包没有安装” 解决办法: yum installl gtk3-devel  ...

  7. 讲真的,千万别得罪会PS的人

    传说中有一种软件炒鸡可怕 那就是PS,专业术语是photoshop! 它能让你貌美如花 也能让你瞬间丑得掉渣 更可怕的是网络上大神的出现 简直让我们难以想象的厉害! 下面大家一起来欣赏一下 那些大神帮 ...

  8. apache的80端口被占用

    1.netstart -ano | findstr "80":查看80端口是否被占用,并找出对应的pid 2.关掉pid对应的进程

  9. 4. Configure maven in Spring Tool Suite

    First of all, you need to copy the folder named like: Choose Window->Preferences->Maven->Us ...

  10. 2018.09.23 孙悟空大战鲤鱼精(单调队列优化dp)

    描述 孙悟空大战鲤鱼精,孙悟空在通天河遇到鲤鱼精,他嫉恶如仇,看见妖精就手痒(忘了自己是妖精).但是鲤鱼精知道孙悟空的厉害,在孙悟空来到通天河,鲤鱼精就跑到了河对面.于是孙悟空就去追鲤鱼精. 我们可以 ...