利用委托机制处理.NET中的异常
概述
在.NET中,可以轻松的通过try-catch块来捕获异常。为了防止在应用程序中出现未处理的异常,可以通过添加一个全局的异常处理函数,如果是多线程的处理,还必须考虑除了主线程之外的工作线程中的异常处理办法,这里用委托机制来实现。
主线程的异常处理
使用Application对象中的ThreadException属性设置一个delegate来捕获所有的未处理的主线程中出现的异常。注意这个全局异常处理程序,只能捕获到主线程中的异常,对于我们自己添加的工作线程、辅助线程的异常是捕获不到的。
在应用程序入口添加全局异常处理:
1
/// <summary>
2
/// 应用程序的主入口点。
3
/// </summary>
4
[STAThread]
5
static void Main()
6
{
7
///添加主线程的全局异常处理
8
Application.ThreadException += new
9
ThreadExceptionEventHandler(
10
MainUIThreadExceptionHandler);
11
12
Application.Run(new Form1());
13
}
/// <summary>2
/// 应用程序的主入口点。3
/// </summary>4
[STAThread]5
static void Main() 6
{ 7
///添加主线程的全局异常处理8
Application.ThreadException += new 9
ThreadExceptionEventHandler(10
MainUIThreadExceptionHandler);11

12
Application.Run(new Form1());13
}
处理程序:
1
public static void MainUIThreadExceptionHandler(Exception ex)
2
{
3
MainUIThreadExceptionHandler(null, new
4
ThreadExceptionEventArgs(ex));
5
}
6
7
/// <summary>
8
/// 主线程全局异常信息的处理
9
/// </summary>
10
/// <param name="sender"></param>
11
/// <param name="t"></param>
12
public static void MainUIThreadExceptionHandler(object
13
sender, ThreadExceptionEventArgs e)
14
{
15
MessageBox.Show(
16
"应用程序发生了如下的异常信息"
17
+ ":" + (char)13
18
+ (char)13 + e.Exception.Message
19
+ (char)13 + (char)13
20
+ "请于系统管理员取得联系!"
21
+ (char)13 + (char)13
22
, "异常信息"
23
, MessageBoxButtons.OK
24
, MessageBoxIcon.Error
25
, MessageBoxDefaultButton.Button1
26
, MessageBoxOptions.ServiceNotification);
27
}
public static void MainUIThreadExceptionHandler(Exception ex)2
{3
MainUIThreadExceptionHandler(null, new4
ThreadExceptionEventArgs(ex));5
}6

7
/// <summary>8
/// 主线程全局异常信息的处理9
/// </summary>10
/// <param name="sender"></param>11
/// <param name="t"></param>12
public static void MainUIThreadExceptionHandler(object13
sender, ThreadExceptionEventArgs e)14
{15
MessageBox.Show(16
"应用程序发生了如下的异常信息"17
+ ":" + (char)1318
+ (char)13 + e.Exception.Message19
+ (char)13 + (char)1320
+ "请于系统管理员取得联系!"21
+ (char)13 + (char)1322
, "异常信息"23
, MessageBoxButtons.OK24
, MessageBoxIcon.Error25
, MessageBoxDefaultButton.Button1 26
, MessageBoxOptions.ServiceNotification); 27
}
工作线程的异常处理
编写多线程代码时,我们必须考虑在工作线程中出现的异常。在线程的入口使用try-catch块,并通过delegate将发生的异常通知给主线程。必须将异常信息通知主线程,否则应用程序不会报错,异常将会消失。
在线程入口使用try-catch块:
1
/// <summary>
2
/// 在线程的入口点加入try-catch块
3
/// </summary>
4
private void DataSave()
5
{
6
try
7
{
8
CreateException();
9
}
10
catch(Exception e)
11
{
12
///通过delegate转向工作线程的异常处理
13
new WorkerThreadExceptionHandlerDelegate(
14
WorkerThreadExceptionHandler).BeginInvoke(e
15
,null
16
,null);
17
}
18
}
/// <summary>2
/// 在线程的入口点加入try-catch块3
/// </summary>4
private void DataSave()5
{6
try7
{8
CreateException();9
}10
catch(Exception e)11
{12
///通过delegate转向工作线程的异常处理13
new WorkerThreadExceptionHandlerDelegate(14
WorkerThreadExceptionHandler).BeginInvoke(e15
,null16
,null);17
}18
}
工作线程异常的处理:
1
/// <summary>
2
/// 声明工作线程的delegate
3
/// </summary>
4
public delegate void
5
WorkerThreadExceptionHandlerDelegate(Exception e);
6
7
/// <summary>
8
/// 工作线程的异常处理
9
/// </summary>
10
/// <param name="e"></param>
11
public void WorkerThreadExceptionHandler(Exception e)
12
{
13
///添加其他的处理代码
14
15
///通知全局异常处理程序
16
MainUIThreadExceptionHandler(
17
this, new System.Threading.
18
ThreadExceptionEventArgs(e));
19
}
/// <summary>2
/// 声明工作线程的delegate3
/// </summary>4
public delegate void5
WorkerThreadExceptionHandlerDelegate(Exception e);6

7
/// <summary>8
/// 工作线程的异常处理9
/// </summary>10
/// <param name="e"></param>11
public void WorkerThreadExceptionHandler(Exception e)12
{13
///添加其他的处理代码14

15
///通知全局异常处理程序16
MainUIThreadExceptionHandler(17
this, new System.Threading.18
ThreadExceptionEventArgs(e));19
}
总结
对于捕获到异常,我们可以Log到文件或者数据库,但是必须保证捕获到所有的异常,以上通过委托机制实现了.NET中的主线程以及工作线程中的异常捕获。
完整的程序代码:
1
using System;
2
using System.Drawing;
3
using System.Collections;
4
using System.ComponentModel;
5
using System.Windows.Forms;
6
using System.Data;
7
using System.Threading;
8
9
namespace UseDelegateException
10
{
11
/// <summary>
12
/// 功能:利用Delegate实现异常的全局处理
13
/// 编写:Terrylee
14
/// 日期:2005年12月10日
15
/// </summary>
16
public class Form1 : System.Windows.Forms.Form
17
{
18
private System.Windows.Forms.Button btnMainUIThread;
19
private System.Windows.Forms.Button btnWorkThread;
20
/// <summary>
21
/// 必需的设计器变量。
22
/// </summary>
23
private System.ComponentModel.Container components = null;
24
25
public Form1()
26
{
27
//
28
// Windows 窗体设计器支持所必需的
29
//
30
InitializeComponent();
31
32
//
33
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
34
//
35
}
36
37
/// <summary>
38
/// 清理所有正在使用的资源。
39
/// </summary>
40
protected override void Dispose( bool disposing )
41
{
42
if( disposing )
43
{
44
if (components != null)
45
{
46
components.Dispose();
47
}
48
}
49
base.Dispose( disposing );
50
}
51
52
Windows 窗体设计器生成的代码 Windows 窗体设计器生成的代码
53
/// <summary>
54
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
55
/// 此方法的内容。
56
/// </summary>
57
private void InitializeComponent()
58
{
59
this.btnMainUIThread = new System.Windows.Forms.Button();
60
this.btnWorkThread = new System.Windows.Forms.Button();
61
this.SuspendLayout();
62
//
63
// btnMainUIThread
64
//
65
this.btnMainUIThread.Location = new System.Drawing.Point(40, 72);
66
this.btnMainUIThread.Name = "btnMainUIThread";
67
this.btnMainUIThread.Size = new System.Drawing.Size(112, 48);
68
this.btnMainUIThread.TabIndex = 0;
69
this.btnMainUIThread.Text = "主线程异常";
70
this.btnMainUIThread.Click += new System.EventHandler(this.btnMainUIThread_Click);
71
//
72
// btnWorkThread
73
//
74
this.btnWorkThread.Location = new System.Drawing.Point(240, 72);
75
this.btnWorkThread.Name = "btnWorkThread";
76
this.btnWorkThread.Size = new System.Drawing.Size(112, 48);
77
this.btnWorkThread.TabIndex = 1;
78
this.btnWorkThread.Text = "工作线程异常";
79
this.btnWorkThread.Click += new System.EventHandler(this.btnWorkThread_Click);
80
//
81
// Form1
82
//
83
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
84
this.ClientSize = new System.Drawing.Size(392, 197);
85
this.Controls.Add(this.btnWorkThread);
86
this.Controls.Add(this.btnMainUIThread);
87
this.MaximizeBox = false;
88
this.Name = "Form1";
89
this.Text = "Form1";
90
this.ResumeLayout(false);
91
92
}
93
#endregion
94
95
/// <summary>
96
/// 应用程序的主入口点。
97
/// </summary>
98
[STAThread]
99
static void Main()
100
{
101
///添加主线程的全局异常处理
102
Application.ThreadException += new
103
ThreadExceptionEventHandler(
104
MainUIThreadExceptionHandler);
105
106
Application.Run(new Form1());
107
}
108
109
public static void MainUIThreadExceptionHandler(Exception ex)
110
{
111
MainUIThreadExceptionHandler(null, new
112
ThreadExceptionEventArgs(ex));
113
}
114
115
/// <summary>
116
/// 主线程全局异常信息的处理
117
/// </summary>
118
/// <param name="sender"></param>
119
/// <param name="t"></param>
120
public static void MainUIThreadExceptionHandler(object
121
sender, ThreadExceptionEventArgs e)
122
{
123
MessageBox.Show(
124
"应用程序发生了如下的异常信息"
125
+ ":" + (char)13
126
+ (char)13 + e.Exception.Message
127
+ (char)13 + (char)13
128
+ "请于系统管理员取得联系!"
129
+ (char)13 + (char)13
130
, "异常信息"
131
, MessageBoxButtons.OK
132
, MessageBoxIcon.Error
133
, MessageBoxDefaultButton.Button1
134
, MessageBoxOptions.ServiceNotification);
135
}
136
137
/// <summary>
138
/// 声明工作线程的delegate
139
/// </summary>
140
public delegate void
141
WorkerThreadExceptionHandlerDelegate(Exception e);
142
143
/// <summary>
144
/// 工作线程的异常处理
145
/// </summary>
146
/// <param name="e"></param>
147
public void WorkerThreadExceptionHandler(Exception e)
148
{
149
///添加其他的处理代码
150
151
///通知全局异常处理程序
152
MainUIThreadExceptionHandler(
153
this, new System.Threading.
154
ThreadExceptionEventArgs(e));
155
}
156
/// <summary>
157
/// 制造异常信息,这里抛出一个除0的异常
158
/// </summary>
159
private void CreateException()
160
{
161
int a = 1;
162
int b = 0;
163
164
int c;
165
c = a/b;
166
}
167
168
/// <summary>
169
/// 在线程的入口点加入try-catch块
170
/// </summary>
171
private void DataSave()
172
{
173
try
174
{
175
CreateException();
176
}
177
catch(Exception e)
178
{
179
///通过delegate转向工作线程的异常处理
180
new WorkerThreadExceptionHandlerDelegate(
181
WorkerThreadExceptionHandler).BeginInvoke(e
182
,null
183
,null);
184
}
185
}
186
187
/// <summary>
188
/// 发生主线程异常
189
/// </summary>
190
/// <param name="sender"></param>
191
/// <param name="e"></param>
192
private void btnMainUIThread_Click(object sender, System.EventArgs e)
193
{
194
///这里出现一个异常,我们不予捕获,交由全局处理函数
195
CreateException();
196
}
197
198
/// <summary>
199
/// 发生工作线程异常
200
/// </summary>
201
/// <param name="sender"></param>
202
/// <param name="e"></param>
203
private void btnWorkThread_Click(object sender, System.EventArgs e)
204
{
205
Thread t = new Thread( new ThreadStart(DataSave));
206
t.Start();
207
}
208
}
209
}
210
using System;2
using System.Drawing;3
using System.Collections;4
using System.ComponentModel;5
using System.Windows.Forms;6
using System.Data;7
using System.Threading;8

9
namespace UseDelegateException10
{11
/// <summary>12
/// 功能:利用Delegate实现异常的全局处理13
/// 编写:Terrylee14
/// 日期:2005年12月10日15
/// </summary>16
public class Form1 : System.Windows.Forms.Form17
{18
private System.Windows.Forms.Button btnMainUIThread;19
private System.Windows.Forms.Button btnWorkThread;20
/// <summary>21
/// 必需的设计器变量。22
/// </summary>23
private System.ComponentModel.Container components = null;24

25
public Form1()26
{27
//28
// Windows 窗体设计器支持所必需的29
//30
InitializeComponent();31

32
//33
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码34
//35
}36

37
/// <summary>38
/// 清理所有正在使用的资源。39
/// </summary>40
protected override void Dispose( bool disposing )41
{42
if( disposing )43
{44
if (components != null) 45
{46
components.Dispose();47
}48
}49
base.Dispose( disposing );50
}51

52
Windows 窗体设计器生成的代码 Windows 窗体设计器生成的代码53
/// <summary>54
/// 设计器支持所需的方法 - 不要使用代码编辑器修改55
/// 此方法的内容。56
/// </summary>57
private void InitializeComponent()58
{59
this.btnMainUIThread = new System.Windows.Forms.Button();60
this.btnWorkThread = new System.Windows.Forms.Button();61
this.SuspendLayout();62
// 63
// btnMainUIThread64
// 65
this.btnMainUIThread.Location = new System.Drawing.Point(40, 72);66
this.btnMainUIThread.Name = "btnMainUIThread";67
this.btnMainUIThread.Size = new System.Drawing.Size(112, 48);68
this.btnMainUIThread.TabIndex = 0;69
this.btnMainUIThread.Text = "主线程异常";70
this.btnMainUIThread.Click += new System.EventHandler(this.btnMainUIThread_Click);71
// 72
// btnWorkThread73
// 74
this.btnWorkThread.Location = new System.Drawing.Point(240, 72);75
this.btnWorkThread.Name = "btnWorkThread";76
this.btnWorkThread.Size = new System.Drawing.Size(112, 48);77
this.btnWorkThread.TabIndex = 1;78
this.btnWorkThread.Text = "工作线程异常";79
this.btnWorkThread.Click += new System.EventHandler(this.btnWorkThread_Click);80
// 81
// Form182
// 83
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);84
this.ClientSize = new System.Drawing.Size(392, 197);85
this.Controls.Add(this.btnWorkThread);86
this.Controls.Add(this.btnMainUIThread);87
this.MaximizeBox = false;88
this.Name = "Form1";89
this.Text = "Form1";90
this.ResumeLayout(false);91

92
}93
#endregion94

95
/// <summary>96
/// 应用程序的主入口点。97
/// </summary>98
[STAThread]99
static void Main() 100
{ 101
///添加主线程的全局异常处理102
Application.ThreadException += new 103
ThreadExceptionEventHandler(104
MainUIThreadExceptionHandler);105

106
Application.Run(new Form1());107
}108
109
public static void MainUIThreadExceptionHandler(Exception ex)110
{111
MainUIThreadExceptionHandler(null, new112
ThreadExceptionEventArgs(ex));113
}114

115
/// <summary>116
/// 主线程全局异常信息的处理117
/// </summary>118
/// <param name="sender"></param>119
/// <param name="t"></param>120
public static void MainUIThreadExceptionHandler(object121
sender, ThreadExceptionEventArgs e)122
{123
MessageBox.Show(124
"应用程序发生了如下的异常信息"125
+ ":" + (char)13126
+ (char)13 + e.Exception.Message127
+ (char)13 + (char)13128
+ "请于系统管理员取得联系!"129
+ (char)13 + (char)13130
, "异常信息"131
, MessageBoxButtons.OK132
, MessageBoxIcon.Error133
, MessageBoxDefaultButton.Button1 134
, MessageBoxOptions.ServiceNotification); 135
}136
137
/// <summary>138
/// 声明工作线程的delegate139
/// </summary>140
public delegate void141
WorkerThreadExceptionHandlerDelegate(Exception e);142

143
/// <summary>144
/// 工作线程的异常处理145
/// </summary>146
/// <param name="e"></param>147
public void WorkerThreadExceptionHandler(Exception e)148
{149
///添加其他的处理代码150

151
///通知全局异常处理程序152
MainUIThreadExceptionHandler(153
this, new System.Threading.154
ThreadExceptionEventArgs(e));155
}156
/// <summary>157
/// 制造异常信息,这里抛出一个除0的异常158
/// </summary>159
private void CreateException()160
{161
int a = 1;162
int b = 0;163

164
int c;165
c = a/b;166
}167
168
/// <summary>169
/// 在线程的入口点加入try-catch块170
/// </summary>171
private void DataSave()172
{173
try174
{175
CreateException();176
}177
catch(Exception e)178
{179
///通过delegate转向工作线程的异常处理180
new WorkerThreadExceptionHandlerDelegate(181
WorkerThreadExceptionHandler).BeginInvoke(e182
,null183
,null);184
}185
}186

187
/// <summary>188
/// 发生主线程异常189
/// </summary>190
/// <param name="sender"></param>191
/// <param name="e"></param>192
private void btnMainUIThread_Click(object sender, System.EventArgs e)193
{194
///这里出现一个异常,我们不予捕获,交由全局处理函数195
CreateException();196
}197
198
/// <summary>199
/// 发生工作线程异常200
/// </summary>201
/// <param name="sender"></param>202
/// <param name="e"></param>203
private void btnWorkThread_Click(object sender, System.EventArgs e)204
{205
Thread t = new Thread( new ThreadStart(DataSave));206
t.Start();207
}208
}209
}210

转载自: http://terrylee.cnblogs.com/archive/2005/12/12/295243.html


浙公网安备 33010602011771号