.net错误处理机制
原地址:http://blog.csdn.net/lxbg90058/article/details/5651767
没有不出错的软件
从不出错的软件从某种程度上讲是不可能的!
和普通人的观念相反,创造可信赖的,健壮的软件并不是一件不可能的事情。大部分的商业软件,在长时间可以无重大故障的工作,但它们并非没有任何的错误,只是拥有低出错率,你可以迅速理解出错原因然后快速搞定它,并且,它不会因为外部错误而毁坏数据。软件中有错误是可以原谅的,甚至是可以预料到的;不可原谅的是您无法解决一个复发的错误,仅仅是因为您没用足够的信息。
另外,假如希望成功避免发生错误,就必须要求开发人员正确对待错误。
做好最坏的打算
所有代码的书写,你应该认为,它是会发生错误的。假如太过于相信自己,往往会导致错误没有被处理,因此也就无法或者非常困难得去获得错误的具体信息。
不要相信外部数据
外部数据是不可相信的。不管这些数据是来自寄存器、数据库、硬盘、socket、文件或者是键盘,它们都必须被检查,只有这样你才可以去使用它们。
唯一可信赖的外部设施是:显示器、鼠标和键盘。
不要理所当然
举个例子,你打开一个txt文件并修改后,希望原地保存,因此往往理所当然地认为,能打开即能保存。然而,该文件可能是只读的,又或者所在驱动器只读,甚至磁盘空间不够。假如你理所当然,那程序也就理所当然地出错了。
合理使用.net异常处理机制
当你摆正观念以后,就可以使用.net完善的异常处理机制,来抒写安全的代码。事实上,并非把握了try{}catch{}语法后,就能抒写安全的代码。其中非常多需要注重的事项。什么时候try?怎么try?怎么catch,都是可以商酌的。我这里介绍的仅仅是比较好的方法。
不要抛出new exception()
exception是一个非常大的类,假如没有side-effect(副作用),很难去捕捉。引用你自己的异常类,但是使它继续自appliationexception。通过这种方法,你可以设计一个专门的异常捕捉程序去捕捉框架抛出的异常,同时设计另一个异常捕捉程序来处理自己抛出的异常。
每个线程要有单独的catch (exception ex)语句
在你的应用程序中,普通的异常处理应该被集中解决。每个线程需要一个单独的try/catch模块,否则,你将会丢失异常导致非常难处理的问题的出现。当一个应用程序启动若干线程去做一些后台处理时,通常你需要创建一个用来存储处理结果的类。不要忘记添加用来存储可能发生的异常的区域,否则在主线程中你将无法与之通信。
要记录exception的全部信息
在捕捉错误以后,应该记录的是exception.tostring(),而不仅是exception.message。exception.tostring()将会给你一个堆栈跟踪内部的异常和信息。通常,这个信息是及其珍贵的,假如你仅记录exception.message,你将会仅仅获得一些没用的信息。
要有清理代码
不要忽略的一件事是try/finally 模块如何使你的代码变得更加可读与健壮,这是处理代码的巨大作用所在。
举个例子,假设你需要从一个临时文件中阅读一些临时信息,然后以字符串的形式返回它。不管发生什么,你都必须删除这一文件。这样的返回处理功能需要try/finally模块来完成。
try
{
string filecontents;
using (streamreader sr = new streamreader(filename))
{
filecontents = sr.readtoend();
}
file.delete(filename);
return filecontents;
}
catch (exception ex)
{
//错误处理
}
finally
{
file.delete(filename);
}
经常使用using
仅仅在一个对象上调用dispose()函数是远远不够的。要害字using将会阻止资源泄漏即使在有异常出现的地方。从上面的例子我们也可以看到这个好处。
当再次抛出异常时不要清空堆栈追踪
堆栈追踪是一个异常携带的最有用的信息之一。经常,我们需要在catch模块中,放入一些异常处理代码(如,回滚一个事务)然后再抛出异常。但很多人会犯下以下的错误:
try
{
// 一些代码
}
catch (exception ex)
{
// 写日志
throw ex;
}
为什么这个是错误的呢?因为,当你检查堆栈跟踪时,异常将会运行到“throw ex”这一行,隐藏了真实的出错位置。你可以试一下。
try
{
//…
}
catch (exception ex)
{
//…
throw;
}
观察以上代码什么改变了呢?取代了这个将会抛出新异常同时清空堆栈追踪的“throw ex;”语句,我们使用了简单的“throw;”语句。假如你没有指定这个异常,throw 声明将会仅仅再次抛出catch声明捕捉的异常。这将会保证你的堆栈追踪完整无缺,但是依然答应你在catch模块中放入代码。
全局错误捕捉
尽管你已经在极大部分的代码里面加入try{}catch{}错误捕捉语句,但依然无法肯定你的代码不会有未捕捉的错误。答应未捕捉错误的发生,会直接让程序非法操作,并且无法获取该错误的具体信息。
全局错误application.threadexception的捕捉能帮你解决这个问题。首先,我们先建立一个用户错误处理类:
/// <summary>
/// 用户错误处理类
/// </summary>
public static class userexception
{
/// <summary>
/// 全局未捕捉错误处理函数
/// </summary>
public static void threadexception(object sender,
system.threading.threadexceptioneventargs e)
{
exception ex = e.exception;
//写日志
application.exit();
}
/// <summary>
/// 全局错误处理函数
/// </summary>
public static void doexception(exception ex)
{
//写日志
}
}
然后在应用程序program类中,添加事件委托:
//委托错误处理事件
application.threadexception += new
system.threading.threadexceptioneventhandler(
userexception.threadexception);
事实上,错误捕捉以后,应用程序应该关闭,而不应该继续运行。但是添加全局错误捕捉以后,可以记录下未知错误的具体信息,甚至做更多的事情,例如:错误发送。
应用程序域级别的错误捕捉
事实上,application.threadexception不是万能的,最重要的一点,它不能捕捉线程级的错误。
这里介绍另外一种错误捕捉appdomain. unhandledexception方法,它是基于应用程序域(一种边界,它由公共语言运行库围绕同一应用程序范围内创建的对象建立。应用程序域有助于将在一个应用程序中创建的对象与在其他应用程序中创建的对象隔离,以使运行时行为可以预知。在一个单独的进程中可以存在多个应用程序域。)级别的。
然而必须告诉你的是,这个方法并不建议用于捕捉线程级的错误。理由有很多,其中一个是,此方法捕捉错误后,程序必须退出,因此无法实现某些中断线程而主进程继续答应的需求。
同样我们需要建立一个应用程序错误处理类:
/// <summary>
/// 应用程序错误处理类
/// </summary>
public static class appexception
{
/// <summary>
/// 整个应用程序域中未捕捉错误处理函数
/// </summary>
public static void domainunhandledexception(object sender,unhandledexceptioneventargs args)
{
exception ex = (exception)args.exceptionobject;
//应用程序必须关闭,只能提前写写日志了
application.exit();
environment.exit(0);
}
}
然后在应用程序program类中,添加事件委托:
//委托错误处理事件
appdomain.currentdomain.unhandledexception += new
unhandledexceptioneventhandler(
appexception.domainunhandledexception);
必须记住的是,捕捉应用程序域的错误以后,程序必须用语句关闭,否则程序依然会发生恐怖非法操作。
线程级的错误捕捉
你会发现,开了多线程的程序,发生错误的几率会大大增加。但是有时候,并不能因为某个线程发生了错误,而必须终止进程。另外,线程中try…catch以后,假如和主进程交互,都是个困难的问题。
不管出于怎样的考虑,都建议把每个线程中捕捉的错误,放到一个专门的类中去处理。假如需要与主进程交互,这个类还应该有委托函数,把处理交给主进程。
/// <summary>
/// 线程错误处理类
/// </summary>
public class workerthreadexception
{
public workerthreadexception()
{
}
public workerthreadexception(exception ex)
{
new workerthreadexceptionhandlerdelegate(
workerthreadexceptionhandler).begininvoke(
ex, null, null);
}
/// <summary>
/// 工作线程错误捕捉委托
/// </summary>
public delegate void workerthreadexceptionhandlerdelegate(
exception ex);
/// <summary>
/// 工作线程错误捕捉处理函数
/// </summary>
public void workerthreadexceptionhandler(exception ex)
{
appexception.unhandledexception(
this,
new system.threading.threadexceptioneventargs(ex));
}
}
可以看到,该类把捕捉到的错误,引发到application.threadexception中,统一处理。当然,你可以做更多的事情。下面,我们创建一个线程:
private void button_click(object sender, eventargs e)
{
//使用独立线程引发错误
thread thread = new thread(new threadstart(testerror));
thread.start();
}
private void testerror()
{
try
{
//除以零
int i = 0;
i = 4 / i;
}
catch (exception ex)
{
new workerthreadexception(ex);
}
}
可以看到,线程中catch到错误后,创建了workerthreadexception类,由该类统一处理,而不是在线程中抒写重复的代码。无论从代码、还是交互角度来看,都建议这样做。
最后
此文并没有介绍调试技巧,然而预防胜于补漏,合理利用.net的异常处理机制,就能很好的捕捉到错误及其信息,减少调试的时间。
最后想说明的是,发生错误并不可怕;可怕的是,错误重复发生,而你却对它一无所知。
.net错误处理机制的更多相关文章
- linux系统编程之错误处理机制
在讲解liunx错误处理机制之前我们先来看一段代码: #include<sys/types.h> #include<sys/stat.h> #include<fcntl. ...
- javascript中的错误处理机制
× 目录 [1]对象 [2]类型 [3]事件[4]throw[5]try[6]常见错误 前面的话 错误处理对于web应用程序开发至关重要,不能提前预测到可能发生的错误,不能提前采取恢复策略,可能导致较 ...
- Map/Reduce 工作机制分析 --- 错误处理机制
前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件 ...
- Android IOS WebRTC 音视频开发总结(七五)-- WebRTC视频通信中的错误恢复机制
本文主要介绍WebRTC视频通信中的错误恢复机制(我们翻译和整理的,译者:jiangpeng),最早发表在[这里] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blac ...
- PHP异常与错误处理机制
先区别一下php中错误 与 异常的概念吧 PHP错误:是属于php程序自身的问题,一般是由非法的语法,环境问题导致的,使得编译器无法通过检查,甚至无法运行的情况.平时遇到的warming.notice ...
- ASP.NET的错误处理机制之一(概念)
对Web应用程序来说,发生不可预知的错误和异常在所难免,我们必须为Web程序提供错误处理机制.当错误发生时,我们必须做好两件事情:一是将错误信息记录日志,发邮件通知网站维护人员,方便技术人员对错误进行 ...
- ASP.NET的错误处理机制
对于一个Web应用程序来说,出错是在所难免的,因此我们应该未雨绸缪,为可能出现的错误提供恰当的处理.事实上,良好的错误处理机制正是衡量Web应用程序好坏的一个重要标准.试想一下,当用户不小心在浏览器输 ...
- hadoop 错误处理机制
hadoop 错误处理机制 1.硬件故障 硬件故障是指jobtracker故障或TaskTracker 故障 jobtracker是单点,若发生故障,目前hadoop 还无法处理,唯有选择最牢靠的硬件 ...
- .net错误处理机制(转)
asp.net 提供了4中错误机制:Page_Error事件>ErrorPage属性>Application_Error事件> <customErrors>配置项 ① P ...
- PHP中的错误处理机制
常见的三种错误: 1.Notice :通知性错误,最小的错误,当发生通知性错误时,会弹出一个提示信息.不会中断代码的执行. 错误代码: #例如Notice: 2.Warning:警告性错误,当发生警告 ...
随机推荐
- facets学习(1):什么是facets
ML 数据集可以包含数亿个数据点,每个数据点由数百(甚至数千)的特征组成,几乎不可能以直观的方式了解整个数据集.为帮助理解.分析和调试 ML 数据集,谷歌开源了 Facets,一款可视化工具. Fac ...
- serversql tinkphp
public function iconv2utf8($Result) { $Row=array(); $key1=array_keys($Res ...
- hdu6231
hdu6231 题意 给出一些数字,对于任意长度不小于 \(k\) 的区间,把第 \(k\) 大数加入到一个新的数组 \(B\) 中,求 \(B\) 数组第 \(m\) 大数. 分析 二分答案 \(x ...
- 前端设计师必须知道的10个重要的CSS技巧
对于一个初入门的前端设计师,在设计修改网站前端的时候,我们需要编写一些CSS.JS的内容达到界面效果.今天分享10个对于前端设计师来说重要的CSS技巧,这也是我在给许多客户做网站的过程当中总结出来的. ...
- [BZOJ3816][清华集训2014]矩阵变换(稳定婚姻问题)
3816: 矩阵变换 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 803 Solved: 578[Submit][Status][Discuss] ...
- POJ 2068 Nim(博弈论)
[题目链接] http://poj.org/problem?id=2068 [题目大意] 给出两队人,交叉放置围成一圈,每个人能取的石子数有个上限,各不相同 轮流取石头,取到最后一块石头的队伍算输,问 ...
- [美团 CodeM 初赛 Round A]最长树链
题目大意: 给你一棵带点权的树,找出一个最长的树链满足链上点权的最大公因数不为1. 思路: 暴力DP. 对于每个点,记录一下以这个点为一个端点的所有链的最大公因数及长度. 然后暴力转移一下,时间复杂度 ...
- 自定义数据类型写入SequenceFile并读出
开头对这边博客的内容做个概述,首先是定义了一个DoubleArrayWritable的类,用于存放矩阵的列向量,然后将其作为value写入SequenceFile中,key就是对应的矩阵的列号,最后( ...
- 【棋盘DP】【OpenJudge7614】最低通行费
最低通行费 总时间限制: 1000ms 内存限制: 65536kB [描述] 一个商人穿过一个 N*N 的正方形的网格,去参加一个非常重要的商务活动.他要从网格的左上角进,右下角出.每穿越中间1个小方 ...
- css layout入门(转)
元素与盒 在HTML中常常使用的概念是元素,而在CSS中,布局的基本单位是盒,盒总是矩形的. 元素与盒并非一一对应的关系,一个元素可能生成多个盒,CSS规则中的伪元素也可能生成盒,display属性为 ...