利用委托机制处理
.NET
中的异常
<?xml:namespace prefix = o ns = “urn:schemas-microsoft-com:office:office” />
Terrylee
,
2005
年
12
月
10
日
概述
在
.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

}
处理程序:
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

}
工作线程的异常处理
编写多线程代码时,我们必须考虑在工作线程中出现的异常。在线程的入口使用
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

}
工作线程异常的处理:
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

}
总结
对于捕获到异常,我们可以
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 窗体设计器生成的代码
#region
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
