利用委托机制处理.NET中的异常

在.NET中,可以轻松的通过try-catch块来捕获异常。为了防止在应用程序中出现未处理的异常,可以通过添加一个全局的异常处理函数,如果是多线程的处理,还必须考虑除了主线程之外的工作线程中的异常处理办法,这里用委托机制来实现。

主线程的异常处理

使用Application对象中的ThreadException属性设置一个delegate来捕获所有的未处理的主线程中出现的异常。注意这个全局异常处理程序,只能捕获到主线程中的异常,对于我们自己添加的工作线程、辅助线程的异常是捕获不到的。

在应用程序入口添加全局异常处理:


/** <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
/**添加主线程的全局异常处理
Application.ThreadException += new
ThreadExceptionEventHandler(
MainUIThreadExceptionHandler);

Application.Run(new Form1());
}

处理程序:


public static void MainUIThreadExceptionHandler(Exception ex)
{
MainUIThreadExceptionHandler(null, new
ThreadExceptionEventArgs(ex));
}

/** <summary>
/// 主线程全局异常信息的处理
/// </summary>
/// <param name="sender"></param>
/// <param name="t"></param>
public static void MainUIThreadExceptionHandler(object
sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(
"应用程序发生了如下的异常信息"
+ ":" + (char)13
+ (char)13 + e.Exception.Message
+ (char)13 + (char)13
+ "请于系统管理员取得联系!"
+ (char)13 + (char)13
, "异常信息"
, MessageBoxButtons.OK
, MessageBoxIcon.Error
, MessageBoxDefaultButton.Button1
, MessageBoxOptions.ServiceNotification);
}


工作线程的异常处理

编写多线程代码时,我们必须考虑在工作线程中出现的异常。在线程的入口使用try-catch块,并通过delegate将发生的异常通知给主线程。必须将异常信息通知主线程,否则应用程序不会报错,异常将会消失。

在线程入口使用try-catch块:


/** <summary>
/// 在线程的入口点加入try-catch块
/// </summary>
private void DataSave()
{
try
{
CreateException();
}
catch(Exception e)
{
/**通过delegate转向工作线程的异常处理
new WorkerThreadExceptionHandlerDelegate(
WorkerThreadExceptionHandler).BeginInvoke(e
,null
,null);
}
}

工作线程异常的处理:


/** <summary>
/// 声明工作线程的delegate
/// </summary>
public delegate void
WorkerThreadExceptionHandlerDelegate(Exception e);

/** <summary>
/// 工作线程的异常处理
/// </summary>
/// <param name="e"></param>
public void WorkerThreadExceptionHandler(Exception e)
{
/**添加其他的处理代码

///通知全局异常处理程序
MainUIThreadExceptionHandler(
this, new System.Threading.
ThreadExceptionEventArgs(e));
}

总结

对于捕获到异常,我们可以Log到文件或者数据库,但是必须保证捕获到所有的异常,以上通过委托机制实现了.NET中的主线程以及工作线程中的异常捕获。


完整的程序代码:


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;

namespace UseDelegateException
{
/** <summary>
/// 功能:利用Delegate实现异常的全局处理
/// 编写:Terrylee
/// 日期:2005年12月10日
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnMainUIThread;
private System.Windows.Forms.Button btnWorkThread;
/** <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();

//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}

/** <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

Windows 窗体设计器生成的代码#region Windows 窗体设计器生成的代码
/** <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.btnMainUIThread = new System.Windows.Forms.Button();
this.btnWorkThread = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnMainUIThread
//
this.btnMainUIThread.Location = new System.Drawing.Point(40, 72);
this.btnMainUIThread.Name = "btnMainUIThread";
this.btnMainUIThread.Size = new System.Drawing.Size(112, 48);
this.btnMainUIThread.TabIndex = 0;
this.btnMainUIThread.Text = "主线程异常";
this.btnMainUIThread.Click += new System.EventHandler(this.btnMainUIThread_Click);
//
// btnWorkThread
//
this.btnWorkThread.Location = new System.Drawing.Point(240, 72);
this.btnWorkThread.Name = "btnWorkThread";
this.btnWorkThread.Size = new System.Drawing.Size(112, 48);
this.btnWorkThread.TabIndex = 1;
this.btnWorkThread.Text = "工作线程异常";
this.btnWorkThread.Click += new System.EventHandler(this.btnWorkThread_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(392, 197);
this.Controls.Add(this.btnWorkThread);
this.Controls.Add(this.btnMainUIThread);
this.MaximizeBox = false;
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

/** <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
/**添加主线程的全局异常处理
Application.ThreadException += new
ThreadExceptionEventHandler(
MainUIThreadExceptionHandler);

Application.Run(new Form1());
}

public static void MainUIThreadExceptionHandler(Exception ex)
{
MainUIThreadExceptionHandler(null, new
ThreadExceptionEventArgs(ex));
}

/** <summary>
/// 主线程全局异常信息的处理
/// </summary>
/// <param name="sender"></param>
/// <param name="t"></param>
public static void MainUIThreadExceptionHandler(object
sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(
"应用程序发生了如下的异常信息"
+ ":" + (char)13
+ (char)13 + e.Exception.Message
+ (char)13 + (char)13
+ "请于系统管理员取得联系!"
+ (char)13 + (char)13
, "异常信息"
, MessageBoxButtons.OK
, MessageBoxIcon.Error
, MessageBoxDefaultButton.Button1
, MessageBoxOptions.ServiceNotification);
}

/** <summary>
/// 声明工作线程的delegate
/// </summary>
public delegate void
WorkerThreadExceptionHandlerDelegate(Exception e);

/** <summary>
/// 工作线程的异常处理
/// </summary>
/// <param name="e"></param>
public void WorkerThreadExceptionHandler(Exception e)
{
/**添加其他的处理代码

///通知全局异常处理程序
MainUIThreadExceptionHandler(
this, new System.Threading.
ThreadExceptionEventArgs(e));
}
/** <summary>
/// 制造异常信息,这里抛出一个除0的异常
/// </summary>
private void CreateException()
{
int a = 1;
int b = 0;

int c;
c = a/b;
}

/** <summary>
/// 在线程的入口点加入try-catch块
/// </summary>
private void DataSave()
{
try
{
CreateException();
}
catch(Exception e)
{
/**通过delegate转向工作线程的异常处理
new WorkerThreadExceptionHandlerDelegate(
WorkerThreadExceptionHandler).BeginInvoke(e
,null
,null);
}
}

/** <summary>
/// 发生主线程异常
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnMainUIThread_Click(object sender, System.EventArgs e)
{
/**这里出现一个异常,我们不予捕获,交由全局处理函数
CreateException();
}

/** <summary>
/// 发生工作线程异常
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnWorkThread_Click(object sender, System.EventArgs e)
{
Thread t = new Thread( new ThreadStart(DataSave));
t.Start();
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值