一、引言
在编写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 )方便调用。在实际使用时,可在继承类中定义多个相同调用接口的方法,避免重复编码,较为方便。
给大家作个参考,而大牛呢,多点指正。当是扔个砖头,想砸块玉吧。
二、代码
2using System.Windows.Forms;
3
4namespace 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 }