一、引言
在编写Windows form时,如果直接在UI线程要运行一个费时方法的话(如从数据库查询大量数据时),会引起程序“假死”,从而导致用户不满。这个时候就需要通过多线程技术来解决,提高界面交互性能,方便用户使用。
一般通过三种方式解决:
1.通过System.Threading.Thread类,创建新的线程,Thread.Start运行费时方法。
2.通过System.Threading.ThreadPool类,将费时任务提交到线程池中,等待运行。
以上两种方法,基本思路是在UI界面中控制线程的启动和中止,在线程中回调用UI界面方法,更新界面。在线程中回调UI界面方法时,特别是涉及更新控件属性时,如果不注意,存在很大的隐患。这两种办法,编码和控制结构较为复杂,需要启动和管理额外的线程占用资源。
3.通过异步委托调用,将该方法排队到系统线程池的线程中运行,而在费时方法中也通过Control.BeginInvoke异步回调,达到"启动后不管"的目的。
这种方法,编码简单,程序结构较为清晰,充分利用.NET框架的异步委托功能,但要对异步调用知识较熟悉。
相关知识点参见
现利用.NET异步委托调用功能,编写Task抽象类,以方便管理后台工作线程,衔接后台线程与UI线程的联系。该抽象类提供了调用和管理的框架,没有方法的实现细节,通过继承类、重写方法,可以实现想要的功能。主要功能如下:
1.利用异步委托调用,实际多线程,不需要单独后台线程。
2.通过委托、事件驱动,实际后台与前台UI线程的联系,实现事件广播。
3.支持正常取消后台工作方法(费时方法)运行,也可以强制中止线程。
4.能够捕获取消、强制中止和方法出错三种情况,并突发相关事件,以便进行释放资源等操作。
5.通过异步调用,在工作方法中安全调用涉及UI控件的方法。
6.自行管理工作进程状态,提供状态变化事件。
7.只要工作方法调用签名,符合定义的TaskDelegate委托接口,可通过StartTask(TaskDelegate worker ,params object[] args )方便调用。在实际使用时,可在继承类中定义多个相同调用接口的方法,避免重复编码,较为方便。
给大家作个参考,而大牛呢,多点指正。当是扔个砖头,想砸块玉吧。
二、代码
1
using System;
2
using System.Windows.Forms;
3
4
namespace Net66.AsynchThread
5

{
6
/**//// <summary>
7
/// 任务工作状态
8
/// </summary>
9
public enum TaskStatus
10
{
11
/**//// <summary>
12
/// 任务没有运行,可能是工作进程没有开始、工作进程正常结束或正常取消工作进程
13
/// </summary>
14
Stopped,
15
/**//// <summary>
16
/// 任务没有运行,被调用者强行中止
17
/// </summary>
18
Aborted,
19
/**//// <summary>
20
/// 任务没有运行,在工作进程中触发错误而中止
21
/// </summary>
22
ThrowErrorStoped,
23
/**//// <summary>
24
/// 任务运行中
25
/// </summary>
26
Running,
27
/**//// <summary>
28
/// 尝试取消工作进程中
29
/// </summary>
30
CancelPending,
31
/**//// <summary>
32
/// 强行中止工作进程中
33
/// </summary>
34
AbortPending
35
36
}
37
38
/**//// <summary>
39
/// 任务状态消息
40
/// </summary>
41
public class TaskEventArgs : EventArgs
42
{
43
/**//// <summary>
44
/// 任务运行结果
45
/// </summary>
46
public Object Result;
47
/**//// <summary>
48
/// 任务进度(0-100)
49
/// </summary>
50
public int Progress;
51
/**//// <summary>
52
/// 任务工作状态
53
/// </summary>
54
public TaskStatus Status;
55
/**//// <summary>
56
/// 任务消息文本
57
/// </summary>
58
public String Message;
59
/**//// <summary>
60
/// 创建任务状态消息
61
/// </summary>
62
/// <param name="progress">任务进度(0-100)</param>
63
public TaskEventArgs( int progress )
64
{
65
this.Progress = progress;
66
this.Status = TaskStatus.Running;
67
}
68
/**//// <summary>
69
/// 创建任务状态消息
70
/// </summary>
71
/// <param name="status">任务线程状态</param>
72
public TaskEventArgs( TaskStatus status )
73
{
74
this.Status = status;
75
}
76
/**//// <summary>
77
/// 创建任务状态消息
78
/// </summary>
79
/// <param name="progress">任务进度(0-100)</param>
80
/// <param name="result">任务运行中间结果</param>
81
public TaskEventArgs( int progress,object result )
82
{
83
this.Progress = progress;
84
this.Status = TaskStatus.Running;
85
this.Result = result;
86
}
87
/**//// <summary>
88
/// 创建任务状态消息
89
/// </summary>
90
/// <param name="status">任务线程状态</param>
91
/// <param name="result">任务运行结果</param>
92
public TaskEventArgs( TaskStatus status,object result )
93
{
94
this.Status = status;
95
this.Result = result;
96
}
97
/**//// <summary>
98
/// 创建任务状态消息
99
/// </summary>
100
/// <param name="status">任务线程状态</param>
101
/// <param name="message">消息文本</param>
102
/// <param name="result">任务运行结果</param>
103
public TaskEventArgs( TaskStatus status,string message ,object result )
104
{
105
this.Status = status;
106
this.Message = message;
107
this.Result = result;
108
}
109
/**//// <summary>
110
/// 创建任务状态消息
111
/// </summary>
112
/// <param name="progress">任务进度(0-100)</param>
113
/// <param name="message">消息文本</param>
114
/// <param name="result">任务运行中间结果</param>
115
public TaskEventArgs( int progress,string message ,object result )
116
{
117
this.Progress = progress;
118
this.Status = TaskStatus.Running;
119
this.Message = message;
120
this.Result = result;
121
}
122
/**//// <summary>
123
/// 创建任务状态消息
124
/// </summary>
125
/// <param name="status">任务线程状态</param>
126
/// <param name="progress">任务进度(0-100)</param>
127
/// <param name="message">消息文本</param>
128
/// <param name="result">任务运行中间结果</param>
129
public TaskEventArgs( TaskStatus status,int progress,string message ,object result )
130
{
131
this.Status = status;
132
this.Progress = progress;
133
this.Message = message;
134
this.Result = result;
135
}
136
}
137
138
/**//// <summary>
139
/// 任务的工作方法(Work)的委托接口
140
/// 传入值:对象数组(object[])
141
/// 返回值:对象(object)
142
/// </summary>
143
public delegate object TaskDelegate( params object[] args );
144
145
/**//// <summary>
146
/// 任务事件的委托接口
147
/// </summary>
148
public delegate void TaskEventHandler( object sender, TaskEventArgs e );
149
150
abstract public class Task
151
{
152
内部属性#region 内部属性
153
/**//// <summary>
154
/// 任务调用线程(前台或UI线程)
155
/// </summary>
156
protected System.Threading.Thread _callThread = null;
157
/**//// <summary>
158
/// 任务工作线程(后台)
159
/// </summary>
160
protected System.Threading.Thread _workThread = null;
161
/**//// <summary>
162
/// 任务工作状态
163
/// </summary>
164
protected TaskStatus _taskState = TaskStatus.Stopped;
165
/**//// <summary>
166
/// 任务进度(0-100)
167
/// </summary>
168
protected int _progress = -1;
169
/**//// <summary>
170
/// 任务工作结果
171
/// </summary>
172
protected object _result = null;
173
/**//// <summary>
174
/// 任务工作进程出错时,捕获的异常对象
175
/// </summary>
176
protected Exception _exception = null;
177
#endregion
178
179
事件#region 事件
180
/**//// <summary>
181
/// 任务工作状态变化事件
182
/// </summary>
183
public event TaskEventHandler TaskStatusChanged;
184
/**//// <summary>
185
/// 任务进度变化事件
186
/// </summary>
187
public event TaskEventHandler TaskProgressChanged;
188
/**//// <summary>
189
/// 任务被调用者强行中止事件
190
/// </summary>
191
public event TaskEventHandler TaskAbort;
192
/**//// <summary>
193
/// 任务工作方法执行中触发错误事件
194
/// </summary>
195
public event TaskEventHandler TaskThrowError;
196
/**//// <summary>
197
/// 任务被调用者取消事件
198
/// </summary>
199
public event TaskEventHandler TaskCancel;
200
#endregion
201
202
属性#region 属性
203
204
/**//// <summary>
205
/// 任务工作进程出错时,捕获的异常对象
206
/// </summary>
207
public Exception Exception
208
{
209
get
{ return _exception;}
210
}
211![]()