快捷搜索:

.Net 下未捕获异常的处理

跟着.Net技巧的成长,.Net技巧被徐徐利用到很多大年夜型的利用软件项目中。这些项目的规模越来越大年夜,很多项目中除了自己的代码外还引用了很多第三方的.net组件。同时很多项目又被利用到很多关键的部门,软件系统的稳定性越来越至关紧张。因为.Net 框架供给了异常强大年夜的非常处置惩罚机制,同时对一些非托管代码很难节制的系统问题比如指针越界,内存透露等供给了很好的办理规划。比拟非托管代码构建的系统,.Net构建的系统加倍稳定。不过这并不是说.Net构建的系统就完全无懈可击,很多因为代码的不严谨或者系统问题激发的故障将会导致.Net利用法度榜样孕育发生未捕获非常,从而导致利用法度榜样非常终止。本文将对三种最常见的.Net利用的未捕获非常处置惩罚进行阐述。

在开始本文之前,让我们来看看.Net在什么环境下会孕育发生未捕获非常。未捕获非常从定义上说便是布局化非常处置惩罚未能捕获的非常。普通的讲便是发生在Try Catch块意外的非常。那么是不是我们在Main函数中加一个Try Catch 块就可以捕获整个未捕获非常了呢?谜底是否定的。这里面有两种环境无法经由过程这种措施捕获:

1. GC 孕育发生的非常,这种非常平日由于Finalize函数中激发未捕获非常引起。当然这并一向对,一些系统问题比如内存耗尽无意偶尔候也会造成GC非常。

2. 主线程以为的线程激发的未捕获非常。这些非常我们每每可以在线程的主函数顶用Try Catch 来捕获,但假如系统中应用了外部的组件,或者以致是.Net 框架自带的一些系统组件,由这些组件的线程激发的非常,调用代码无法经由过程Try Catch来捕获。

从上面两点来看,纵然我们的代码在每个地方都加了Try Catch ,也不能百分百杜绝未捕获非常的发生。

鉴于此,为了前进系统的壮实性和可掩护性,我们必要经由过程一种措施来截获这些未捕获非常,并进行适当的处置惩罚。

.Net 的设计者已经斟酌到这些问题,并且为我们供给了一个叫 UnhandledExceptionEventHandler 的事故,经由过程这个事故,我们可以截获未捕获非常,并进行处置惩罚。

这个事故的事故参数UnhandledExceptionEventArgs e, 有两个属性,一个是ExceptionObject,这个属性返回为截获非常的工具实例。还有一个属性是IsTerminating,这个属性奉告我们这个非常是否会导致利用终止。这里必要阐明的是,对付.Net1.1 和 .Net2.0及以上,环境是不一样的,.Net1.1 只有在主线程中的未捕获非常才会终止利用法度榜样,而.Net2.0及以上版本则是始终终止利用法度榜样。假如不终止利用法度榜样,而是有CLR 将当前非常消化,系统的运行状态很可能弗成控,着末可能会发生更大年夜的故障,以是.Net2.0今后,对付所有未捕获非常,一律终止当前利用。这样看来,对付.net2.0以上的利用彷佛我们截获未捕获非常已经毫无意义,着实不然。经由过程截获为未捕获非常,我们可以记录下法度榜样是再哪里孕育发生这种未捕获非常的,以便法度榜样的开拓者改进法度榜样。我们也可以在当前利用退出前为系统做一些其他的保护事情,比如备份数据,告警提示等等。

下面我们来看看三种常见的.Net利用分手若何来截获未捕获非常。

节制台利用

首先为当前AppDomain 添加 UnhandledExceptionEventHandler

AppDomain.CurrentDomain.UnhandledException +=

new UnhandledExceptionEventHandler(UnhandledExceptionEventHandler);

再添加事故相应函数

static void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e)

{

try

{

using (System.IO.FileStream fs = new System.IO.FileStream(@"c:testme.log",

System.IO.FileMode.Append, System.IO.FileAccess.Write))

{

using (System.IO.StreamWriter w = new System.IO.StreamWriter(fs,

System.Text.Encoding.UTF8))

{

w.WriteLine(e.ExceptionObject);

}

}

}

catch

{

}

}

System.DivideByZeroException: Attempted to divide by zero.

at TestCosole.Program.TestRaiseException.Finalize()

WinForm

WinForm 利用经由过程 Application.ThreadException 变糊弄截获未捕获非常

详见 园子里面另一篇博客,这里就不再冗诉。

体面地处置惩罚法度榜样的未捕获非常

Asp.net

ASP.NET 利用和前两种利用有所不合,ASP.NET 一样平常在后台线程或者线程池中孕育发生未捕获非常,才会导致W3WP.exe终止,并在事故查看器中孕育发生一条类似下面内容的事故:EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.1830, P3 42435be1, P4 app_web_ncsnb2-n, P5 0.0.0.0, P6 440a4082, P7 5, P8 1, P9 system.nullreferenceexception, P10 NIL.

要截获ASP.NET 的未捕获非常,我们必要为每个利用法度榜样域安装事故钩子

这个历程必要分两步完成:

起开创建一个实现IHttpModule接口的类

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

namespace WebMonitor

{

/**////

/// Summary description for UnhandledExceptionModule

///

public class UnhandledExceptionModule : IHttpModule

{

static object _initLock = new object();

static bool _initialized = false;

public UnhandledExceptionModule()

{

//

// TODO: Add constructor logic here

//

}

void OnUnhandledException(object o, UnhandledExceptionEventArgs e)

{

//Do some thing you wish to do when the Unhandled Exception raised.

try

{

using (System.IO.FileStream fs = new System.IO.FileStream(@"c:testme.log",

System.IO.FileMode.Append, System.IO.FileAccess.Write))

{

using (System.IO.StreamWriter w = new System.IO.StreamWriter(fs, System.

Text.Encoding.UTF8))

{

w.WriteLine(e.ExceptionObject);

}

}

}

catch

{

}

}

IHttpModule Members#region IHttpModule Members

public void Dispose()

{

throw new Exception("The method or operation is not implemented.");

}

public void Init(HttpApplication context)

{

// Do this one time for each AppDomain.

lock (_initLock)

{

if (!_initialized)

{

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);

_initialized = true;

}

}

}

#endregion

}

}

您可能还会对下面的文章感兴趣: