利用委托机制处理.NET中的异常(Multi thread)
利用委托机制处理.NET中的异常
概述
在.NET中,可以轻松的通过try-catch块来捕获异常。为了防止在应用程序中出现未处理的异常,可以通过添加一个全局的异常处理函数,如果是多线程的处理,还必须考虑除了主线程之外的工作线程中的异常处理办法,这里用委托机制来实现。
主线程的异常处理
使用Application对象中的ThreadException属性设置一个delegate来捕获所有的未处理的主线程中出现的异常。注意这个全局异常处理程序,只能捕获到主线程中的异常,对于我们自己添加的工作线程、辅助线程的异常是捕获不到的。
(Application.ThreadException(注意:这个事件需要关闭 JIT 异常调试功能再能被引发)和 AppDomain.CurrentDomain.UnhandledException 两个事件。)
在应用程序入口添加全局异常处理:
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
}

2

3

4

5

6

7

8

9

10

11

12

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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

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