【转】衔接UI线程和管理后台工作线程的类(多线程、异步调用)

衔接UI线程和管理后台工作线程的类(多线程、异步调用)

转:http://www.cnblogs.com/net66/archive/2005/08/03/206132.html

一、引言
     在编写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 ExpandedBlockStart.gifContractedBlock.gif {
  6ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
  7    /// 任务工作状态
  8    /// </summary>

  9    public enum TaskStatus 
 10ExpandedSubBlockStart.gifContractedSubBlock.gif    
 11ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 12        /// 任务没有运行,可能是工作进程没有开始、工作进程正常结束或正常取消工作进程
 13        /// </summary>

 14        Stopped, 
 15ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 16        /// 任务没有运行,被调用者强行中止
 17        /// </summary>

 18        Aborted,
 19ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 20        /// 任务没有运行,在工作进程中触发错误而中止
 21        /// </summary>

 22        ThrowErrorStoped,
 23ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 24        /// 任务运行中
 25        /// </summary>

 26        Running, 
 27ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 28        /// 尝试取消工作进程中
 29        /// </summary>

 30        CancelPending,
 31ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 32        /// 强行中止工作进程中
 33        /// </summary>

 34        AbortPending
 35
 36    }
 
 37
 38ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 39    /// 任务状态消息
 40    /// </summary>

 41    public class TaskEventArgs : EventArgs 
 42ExpandedSubBlockStart.gifContractedSubBlock.gif    
 43ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 44        /// 任务运行结果
 45        /// </summary>

 46        public Object     Result; 
 47ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 48        /// 任务进度(0-100)
 49        /// </summary>

 50        public int        Progress; 
 51ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 52        /// 任务工作状态
 53        /// </summary>

 54        public TaskStatus Status; 
 55ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 56        /// 任务消息文本
 57        /// </summary>

 58        public String Message;
 59ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 60        /// 创建任务状态消息
 61        /// </summary>
 62        /// <param name="progress">任务进度(0-100)</param>

 63        public TaskEventArgs( int progress ) 
 64ExpandedSubBlockStart.gifContractedSubBlock.gif        
 65            this.Progress = progress; 
 66            this.Status   = TaskStatus.Running; 
 67        }
 
 68ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 69        /// 创建任务状态消息
 70        /// </summary>
 71        /// <param name="status">任务线程状态</param>

 72        public TaskEventArgs( TaskStatus status ) 
 73ExpandedSubBlockStart.gifContractedSubBlock.gif        
 74            this.Status = status; 
 75        }
 
 76ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 77        /// 创建任务状态消息
 78        /// </summary>
 79        /// <param name="progress">任务进度(0-100)</param>
 80        /// <param name="result">任务运行中间结果</param>

 81        public TaskEventArgs( int progress,object result ) 
 82ExpandedSubBlockStart.gifContractedSubBlock.gif        
 83            this.Progress = progress; 
 84            this.Status   = TaskStatus.Running; 
 85            this.Result   = result;
 86        }
 
 87ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 88        /// 创建任务状态消息
 89        /// </summary>
 90        /// <param name="status">任务线程状态</param>
 91        /// <param name="result">任务运行结果</param>

 92        public TaskEventArgs( TaskStatus status,object result ) 
 93ExpandedSubBlockStart.gifContractedSubBlock.gif        
 94            this.Status   = status; 
 95            this.Result   = result;
 96        }
 
 97ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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 ) 
104ExpandedSubBlockStart.gifContractedSubBlock.gif        
105            this.Status   = status; 
106            this.Message = message;
107            this.Result   = result;
108        }
 
109ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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 ) 
116ExpandedSubBlockStart.gifContractedSubBlock.gif        
117            this.Progress = progress; 
118            this.Status   = TaskStatus.Running; 
119            this.Message = message;
120            this.Result   = result;
121        }
 
122ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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 ) 
130ExpandedSubBlockStart.gifContractedSubBlock.gif        
131            this.Status = status;
132            this.Progress = progress; 
133            this.Message = message;
134            this.Result   = result;
135        }
 
136    }
     
137
138ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
139    /// 任务的工作方法(Work)的委托接口
140    /// 传入值:对象数组(object[])
141    /// 返回值:对象(object)
142    /// </summary>

143    public delegate object TaskDelegate( params object[] args ); 
144
145ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
146    /// 任务事件的委托接口
147    /// </summary>

148    public delegate void TaskEventHandler( object sender, TaskEventArgs e ); 
149
150    abstract public class Task
151ExpandedSubBlockStart.gifContractedSubBlock.gif    {   
152ExpandedSubBlockStart.gifContractedSubBlock.gif        内部属性#region 内部属性
153ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
154        /// 任务调用线程(前台或UI线程)
155        /// </summary>

156        protected System.Threading.Thread _callThread = null
157ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
158        /// 任务工作线程(后台)
159        /// </summary>

160        protected System.Threading.Thread _workThread = null
161ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
162        /// 任务工作状态
163        /// </summary>

164        protected TaskStatus _taskState = TaskStatus.Stopped; 
165ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
166        /// 任务进度(0-100)
167        /// </summary>

168        protected int _progress = -1;
169ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
170        /// 任务工作结果
171        /// </summary>

172        protected object _result = null;
173ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
174        /// 任务工作进程出错时,捕获的异常对象
175        /// </summary>

176        protected Exception _exception = null;
177        #endregion

178
179ExpandedSubBlockStart.gifContractedSubBlock.gif        事件#region 事件
180ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
181        /// 任务工作状态变化事件
182        /// </summary>

183        public event TaskEventHandler TaskStatusChanged; 
184ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
185        /// 任务进度变化事件
186        /// </summary>

187        public event TaskEventHandler TaskProgressChanged; 
188ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
189        /// 任务被调用者强行中止事件
190        /// </summary>

191        public event TaskEventHandler TaskAbort; 
192ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
193        /// 任务工作方法执行中触发错误事件
194        /// </summary>

195        public event TaskEventHandler TaskThrowError; 
196ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
197        /// 任务被调用者取消事件
198        /// </summary>

199        public event TaskEventHandler TaskCancel; 
200        #endregion

201
202ExpandedSubBlockStart.gifContractedSubBlock.gif        属性#region 属性
203        
204ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
205        /// 任务工作进程出错时,捕获的异常对象
206        /// </summary>

207        public Exception Exception
208ExpandedSubBlockStart.gifContractedSubBlock.gif        {
209ExpandedSubBlockStart.gifContractedSubBlock.gif            get return _exception;}
210        }

211ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
212        /// 任务调用线程(前台或UI线程)
213        /// </summary>

214        public System.Threading.Thread CallThread
215ExpandedSubBlockStart.gifContractedSubBlock.gif        {
216ExpandedSubBlockStart.gifContractedSubBlock.gif            get return _callThread;}
217        }

218ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
219        /// 任务工作线程(后台)
220        /// </summary>

221        public System.Threading.Thread WordThread
222ExpandedSubBlockStart.gifContractedSubBlock.gif        {
223ExpandedSubBlockStart.gifContractedSubBlock.gif            get {return _workThread;}
224        }

225        
226ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
227        /// 任务进度(0-100)
228        /// </summary>

229        public int Progress
230ExpandedSubBlockStart.gifContractedSubBlock.gif        {
231ExpandedSubBlockStart.gifContractedSubBlock.gif            get {return _progress;} 
232        }

233ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
234        /// 任务工作状态
235        /// </summary>

236        public TaskStatus TaskState
237ExpandedSubBlockStart.gifContractedSubBlock.gif        {
238ExpandedSubBlockStart.gifContractedSubBlock.gif            get {return _taskState;}
239        }

240ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
241        /// 任务工作结果
242        /// </summary>

243        public object Result
244ExpandedSubBlockStart.gifContractedSubBlock.gif        {
245ExpandedSubBlockStart.gifContractedSubBlock.gif            get {return _result;}
246        }

247
248        protected bool IsStop
249ExpandedSubBlockStart.gifContractedSubBlock.gif        {
250            get
251ExpandedSubBlockStart.gifContractedSubBlock.gif            {
252                bool result = false;
253                switch (_taskState)
254ExpandedSubBlockStart.gifContractedSubBlock.gif                {
255                    case TaskStatus.Stopped:
256                    case TaskStatus.Aborted:
257                    case TaskStatus.ThrowErrorStoped:
258                        result = true;
259                        break;
260                    default:
261                        break;
262                }

263                return result;
264            }

265        }

266        #endregion

267
268ExpandedSubBlockStart.gifContractedSubBlock.gif        触发事件#region 触发事件
269ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
270        /// 触发任务工作状态变化事件
271        /// </summary>
272        /// <param name="status">任务工作状态</param>
273        /// <param name="result">任务工作结果对象</param>

274        protected void FireStatusChangedEvent(TaskStatus status, object result) 
275ExpandedSubBlockStart.gifContractedSubBlock.gif        
276            if( TaskStatusChanged != null ) 
277ExpandedSubBlockStart.gifContractedSubBlock.gif            
278                TaskEventArgs args = new TaskEventArgs( status,result); 
279                AsyncInvoke(TaskStatusChanged,args);
280            }
 
281        }
 
282 
283ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
284        /// 触发任务进度变化事件
285        /// </summary>
286        /// <param name="progress">任务进度(0-100)</param>
287        /// <param name="result">任务工作中间结果对象</param>

288        protected void FireProgressChangedEvent(int progress, object result) 
289ExpandedSubBlockStart.gifContractedSubBlock.gif        
290            if( TaskProgressChanged != null ) 
291ExpandedSubBlockStart.gifContractedSubBlock.gif            
292                TaskEventArgs args = new TaskEventArgs( progress,result); 
293                AsyncInvoke(TaskProgressChanged,args);
294            }
 
295        }
 
296ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
297        /// 触发工作方法执行中发现错误事件
298        /// </summary>
299        /// <param name="progress">任务进度(0-100)</param>
300        /// <param name="result">任务工作中间结果对象</param>

301        protected void FireThrowErrorEvent(int progress, object result) 
302ExpandedSubBlockStart.gifContractedSubBlock.gif        
303            if( TaskThrowError != null ) 
304ExpandedSubBlockStart.gifContractedSubBlock.gif            
305                TaskEventArgs args = new TaskEventArgs( progress,result); 
306                AsyncInvoke(TaskThrowError,args);
307            }
 
308        }
 
309ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
310        /// 触发被调用者取消事件
311        /// </summary>
312        /// <param name="progress">任务进度(0-100)</param>
313        /// <param name="result">任务工作中间结果对象</param>

314        protected void FireCancelEvent(int progress, object result) 
315ExpandedSubBlockStart.gifContractedSubBlock.gif        
316            if( TaskCancel != null ) 
317ExpandedSubBlockStart.gifContractedSubBlock.gif            
318                TaskEventArgs args = new TaskEventArgs( progress,result); 
319                AsyncInvoke(TaskCancel,args);
320            }
 
321        }
 
322ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
323        /// 触发被调用者强行中止事件
324        /// </summary>
325        /// <param name="progress">任务进度(0-100)</param>
326        /// <param name="result">任务工作中间结果对象</param>

327        protected void FireAbortEvent(int progress, object result) 
328ExpandedSubBlockStart.gifContractedSubBlock.gif        
329            if( TaskAbort != null ) 
330ExpandedSubBlockStart.gifContractedSubBlock.gif            
331                TaskEventArgs args = new TaskEventArgs( progress,result); 
332                AsyncInvoke(TaskAbort,args);
333            }
 
334        }
 
335ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
336        /// 异步调用挂接事件委托
337        /// </summary>
338        /// <param name="eventhandler">事件处理方法句柄</param>
339        /// <param name="args">事件消息</param>

340        protected void AsyncInvoke(TaskEventHandler eventhandler,TaskEventArgs args)
341ExpandedSubBlockStart.gifContractedSubBlock.gif        {
342//            TaskEventHandler[] tpcs = (TaskEventHandler[])eventhandler.GetInvocationList();
343            Delegate[] tpcs = eventhandler.GetInvocationList();
344            foreach(TaskEventHandler tpc in tpcs)
345ExpandedSubBlockStart.gifContractedSubBlock.gif            {
346                if ( tpc.Target is System.Windows.Forms.Control ) 
347ExpandedSubBlockStart.gifContractedSubBlock.gif                
348                    Control targetForm = tpc.Target as System.Windows.Forms.Control; 
349ExpandedSubBlockStart.gifContractedSubBlock.gif                    targetForm.BeginInvoke( tpc,new object[] this, args } ); 
350                }
 
351                else 
352ExpandedSubBlockStart.gifContractedSubBlock.gif                
353                    tpc.BeginInvoke(this, args ,null,null); //异步调用,启动后不管
354                }

355            }
        
356        }

357        #endregion

358
359ExpandedSubBlockStart.gifContractedSubBlock.gif        工作进程管理#region 工作进程管理
360ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
361        /// 开启任务默认的工作进程
362        /// [public object Work(params  object[] args )]
363        /// </summary>
364        /// <param name="args">传入的参数数组</param>

365        public bool StartTask( params object[] args ) 
366ExpandedSubBlockStart.gifContractedSubBlock.gif        
367            return StartTask(new TaskDelegate( Work ),args); 
368        }
 
369ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
370        /// 开启任务的工作进程
371        /// 将开启符合TaskDelegate委托接口的worker工作方法
372        /// </summary>
373        /// <param name="worker">工作方法</param>
374        /// <param name="args">传入的参数数组</param>

375        public bool StartTask(TaskDelegate worker ,params object[] args ) 
376ExpandedSubBlockStart.gifContractedSubBlock.gif        
377            bool result =false;
378            lockthis ) 
379ExpandedSubBlockStart.gifContractedSubBlock.gif            
380                if( IsStop && worker != null ) 
381ExpandedSubBlockStart.gifContractedSubBlock.gif                
382                    _result = null;
383                    _callThread = System.Threading.Thread.CurrentThread;
384                    // 开始工作方法进程,异步开启,传送回调方法
385                    worker.BeginInvoke( args ,new AsyncCallback( EndWorkBack ), worker ); 
386                    // 更新任务工作状态
387                    _taskState = TaskStatus.Running; 
388                    // 触发任务工作状态变化事件
389                    FireStatusChangedEvent( _taskState, null); 
390                    result = true;
391                }
 
392            }
 
393            return result;
394        }
 
395ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
396        /// 请求停止任务进程
397        /// 是否停止成功,应看任务工作状态属性TaskState是否为TaskStatus.Stop
398        /// </summary>

399        public bool StopTask() 
400ExpandedSubBlockStart.gifContractedSubBlock.gif        
401            bool result =false;
402            lockthis ) 
403ExpandedSubBlockStart.gifContractedSubBlock.gif            
404                if( _taskState == TaskStatus.Running ) 
405ExpandedSubBlockStart.gifContractedSubBlock.gif                
406                    // 更新任务工作状态 
407                    _taskState = TaskStatus.CancelPending; 
408                    // 触发任务工作状态变化事件
409                    FireStatusChangedEvent( _taskState, _result); 
410                    result = true;
411                }
 
412            }
 
413            return result;
414        }
 
415ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
416        /// 强行中止任务的工作线程
417        /// 
418        /// </summary>

419        public bool AbortTask() 
420ExpandedSubBlockStart.gifContractedSubBlock.gif        
421            bool result = false;
422            lockthis ) 
423ExpandedSubBlockStart.gifContractedSubBlock.gif            
424                if( _taskState == TaskStatus.Running && _workThread != null ) 
425ExpandedSubBlockStart.gifContractedSubBlock.gif                
426                    if (_workThread.ThreadState != System.Threading.ThreadState.Stopped)
427ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
428                        _workThread.Abort();
429                    }

430                    System.Threading.Thread.Sleep(2);
431                    if (_workThread.ThreadState == System.Threading.ThreadState.Stopped)
432ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
433                        // 更新任务工作状态 
434                        _taskState = TaskStatus.Aborted; 
435                        result = true;
436                    }

437                    else
438ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
439                        // 更新任务工作状态 
440                        _taskState = TaskStatus.AbortPending; 
441                        result = false;
442                    }

443                    // 触发任务工作状态变化事件
444                    FireStatusChangedEvent( _taskState, _result); 
445                }
 
446            }
 
447            return result;
448        }
 
449
450ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
451        /// 工作方法完成后的回调方法
452        /// 将检查是否出错,并获取、更新返回结果值
453        /// </summary>
454        /// <param name="ar">异步调用信号对象</param>

455        protected void EndWorkBack( IAsyncResult ar ) 
456ExpandedSubBlockStart.gifContractedSubBlock.gif        
457            bool error = false;
458            bool abort = false;
459            try                                                //检查是否错误
460ExpandedSubBlockStart.gifContractedSubBlock.gif            {
461                TaskDelegate del = (TaskDelegate)ar.AsyncState; 
462                _result = del.EndInvoke( ar ); 
463            }

464            catch(Exception e)                                //如果错误,则保存错误对象
465ExpandedSubBlockStart.gifContractedSubBlock.gif            {
466                error = true;
467                _exception = e;
468                if (e.GetType() == typeof(System.Threading.ThreadAbortException))
469ExpandedSubBlockStart.gifContractedSubBlock.gif                {
470                    abort = true;
471                    FireAbortEvent(_progress,_exception);
472                }

473                else
474ExpandedSubBlockStart.gifContractedSubBlock.gif                {
475                    FireThrowErrorEvent(_progress,_exception);
476                }

477            }

478            lockthis ) 
479ExpandedSubBlockStart.gifContractedSubBlock.gif            
480                if (error)
481ExpandedSubBlockStart.gifContractedSubBlock.gif                {
482                    if ( abort)
483ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
484                        _taskState = TaskStatus.Aborted;        //调用者强行中止
485                    }

486                    else
487ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
488                        _taskState = TaskStatus.ThrowErrorStoped;//出现错误而中止
489                    }

490                }
 
491                else
492ExpandedSubBlockStart.gifContractedSubBlock.gif                {    _taskState = TaskStatus.Stopped;}          //正常结束
493                FireStatusChangedEvent( _taskState, _result);
494            }
 
495        }
 
496        #endregion

497
498ExpandedSubBlockStart.gifContractedSubBlock.gif        工作方法的基础#region 工作方法的基础
499ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
500        /// 工作方法
501        /// 在继承类中应重写(override)此方法,以实现具体的工作内容,注意以几点:
502        /// 1.须在继承类是引用base.Work,在基类(base)的Work方法中,执行线程设为IsBackground=true,并保存工作线程对象
503        /// 2.在继承类中,应及时更新_progress与_result对象,以使Progress和Result属性值正确
504        /// 3.在执行过程中应检查_taskState,以使任务中被请求停止后(_taskState为TaskStatus.CancelPending),工作线程能最快终止.
505        /// 4.如在继承类中新定义了事件,应在此方法中引用触发
506        /// 5.工作线程状态不由工作方法管理,所以在工作方法中不应改变_taskState变量值
507        /// 6.工作方法中应对args参数进行有效检查
508        /// </summary>
509        /// <param name="args">传入的参数数组</param>
510        /// <returns>返回null</returns>

511        virtual public object Work(params  object[] args )
512ExpandedSubBlockStart.gifContractedSubBlock.gif        {
513            System.Threading.Thread.CurrentThread.IsBackground = true;
514            _workThread = System.Threading.Thread.CurrentThread;
515            _result = null;
516            return null;
517        }

518
519        #endregion

520    }

521}

522
523 ExpandedBlockStart.gifContractedBlock.gif 使用Task类 #region 使用Task类
524ExpandedSubBlockStart.gifContractedSubBlock.gif/**//*
525
526使用 Task 类
527
528一.在UI线程中创建Task类
529
530Task 类负责管理后台线程。要使用 Task 类,必须做的事情就是创建一个 Task 对象,注册它激发的事件,并且实现这些事件的处理。因为事件是在 UI 线程上激发的,所以您根本不必担心代码中的线程处理问题。
531
532下面的示例展示了如何创建 Task 对象。现假设UI 有两个按钮,一个用于启动运算,一个用于停止运算,还有一个进度栏显示当前的计算进度。
533
534// 创建任务管理对象
535_Task = new Task(); 
536// 挂接任务管理对象工作状态变化事件
537_Task.TaskStatusChanged += new TaskEventHandler( OnTaskStatusChanged ); 
538// 挂接任务管理对象工作进度变化事件
539_Task.TaskProgressChanged += new TaskEventHandler( OnTaskProgressChanged ); 
540
541(1)
542用于计算状态和计算进度事件的事件处理程序相应地更新 UI,例如通过更新状态栏控件。 
543
544private void OnTaskProgressChanged( object sender,TaskEventArgs e ) 
545
546    _progressBar.Value = e.Progress; 
547
548(2)
549下面的代码展示的 TaskStatusChanged 事件处理程序更新进度栏的值以反映当前的计算进度。假定进度栏的最小值和最大值已经初始化。
550
551private void OnTaskStatusChanged( object sender, TaskEventArgs e ) 
552
553    switch ( e.Status ) 
554    { 
555        case TaskStatus.Running: 
556            button1.Enabled = false; 
557            button2.Enabled = true; 
558            break; 
559        case TaskStatus.Stop: 
560            button1.Enabled = true; 
561            button2.Enabled = false; 
562            break; 
563        case TaskStatus.CancelPending: 
564            button1.Enabled = false; 
565            button2.Enabled = false; 
566            break; 
567    } 
568
569
570在这个示例中,TaskStatusChanged 事件处理程序根据计算状态启用和禁用启动和停止按钮。这可以防止用户尝试启动一个已经在进行的计算,并且向用户提供有关计算状态的反馈。
571
572通过使用 Task 对象中的公共方法,UI 为每个按钮单击实现了窗体事件处理程序,以便启动和停止计算。例如,启动按钮事件处理程序调用 StartTask 方法,如下所示。
573
574private void startButton_Click( object sender, System.EventArgs e ) 
575
576    _Task.StartTask( new object[] {} ); 
577
578
579类似地,停止计算按钮通过调用 StopTask 方法来停止计算,如下所示。
580
581private void stopButton_Click( object sender, System.EventArgs e ) 
582
583    _Task.StopTask(); 
584
585
586二.可能在非UI线程中使用Task类时
587(1)和(2)应作如下改变
588
589(1)
590用于计算状态和计算进度事件的事件处理程序相应地更新 UI,例如通过更新状态栏控件。 
591
592private void OnTaskProgressChanged( object sender,TaskEventArgs e ) 
593
594    if (InvokeRequired )        //不在UI线程上,异步调用
595    {
596        TaskEventHandler TPChanged = new TaskEventHandler( OnTaskProgressChanged ); 
597        this.BeginInvoke(TPChanged,new object[] {sender,e});
598    }
599    else                        //更新
600    {
601        _progressBar.Value = e.Progress; 
602    }
603
604(2)
605下面的代码展示的 TaskStatusChanged 事件处理程序更新进度栏的值以反映当前的计算进度。假定进度栏的最小值和最大值已经初始化。
606
607private void OnTaskStatusChanged( object sender, TaskEventArgs e ) 
608
609    if (InvokeRequired )        //不在UI线程上,异步调用
610    {
611        TaskEventHandler TSChanged = new TaskEventHandler( OnTaskStatusChanged ); 
612        this.BeginInvoke(TSChanged,new object[] {sender,e});
613    }
614    else                        //更新
615    {
616        switch ( e.Status ) 
617        { 
618            case TaskStatus.Running: 
619                button1.Enabled = false; 
620                button2.Enabled = true; 
621                break; 
622            case TaskStatus.Stop: 
623                button1.Enabled = true; 
624                button2.Enabled = false; 
625                break; 
626            case TaskStatus.CancelPending: 
627                button1.Enabled = false; 
628                button2.Enabled = false; 
629                break; 
630        } 
631    }
632
633
634*/

635#endregion

636



三、示例
1.启动时的UI界面


2.后台工作方法(费用方法)运行后,任务状态为Running


3.强制中止工作方法,运行任务状态Aborted


4.工作方法突发错误时,任务状态ThrowErrorStoped


5.工作方法正常结束或正常取消而结束时,任务状态Stopped


示例代码下载

posted on 2005-08-03 00:19 Net66 阅读(5867) 评论(27)  编辑 收藏 所属分类: C#

评论

  2005-08-03 00:50  
good. 多线程的文章比较少, 下次谈谈同步的问题吧.
            
  2005-08-03 01:50  
学习。
            
 218.81.148.* 2005-08-03 07:11 
很好,收藏研究.
          
 218.249.96.* 2005-08-03 08:46 
System.Threading.ThreadPool还是不要用的好,这东西牵扯进程的异步调用,这东西微软就该设置成internal
          
 222.43.70.* 2005-08-03 08:49 
          
  2005-08-03 08:54  
这些BeginXXXX的方法都是使用了ThreadPool的。
            
 222.47.87.* 2005-08-03 09:06 
刚完成了一个图库管理系统, 使用的就是这种方式. 感觉还不错.
          
 218.79.240.* 2005-08-03 09:08 
文章的意思应该是不用显式使用ThreadPool,通过系统默认调用吧
          
  2005-08-03 09:23  
好文章。。
            
  2005-08-03 09:39  
异步委托也是刚刚用过,做一个分析目录的工具的时候用的。
            
  2005-08-03 09:41  
我的意思是说,这些异步委托调用什么的,其内部都是使用了ThreadPool的,这样当然不用你自己去直接使用ThreadPool了。
            
  2005-08-03 18:48  
最近写的项目中因为用得很多网络交互,频繁的异步调用,但对控制这些线程却没有一点主意,希望能从你的文章中得到一些启示。
            
  2005-09-12 18:34  
研究中、。。。
太好了 还有源码,可以少走一些弯路了
谢谢!
            
  2005-09-14 16:10  
看了下楼主的代码,大致上不错。不过在封装性方面做得不够...其实封装性是需要早一些构思的,比功能的实现还要再早一些。
先搞清楚你的Task的派生类依赖什么,也就是说可供派生类调用的方法,例如Fire***方法;接下来搞清楚你的Task的派生类不依赖什么,例如必须在重写方法中调用base.Work这样的问题;最后是参数的传递问题。由此我想到了在Delphi3中对Thread的封装,有一个同步执行方法的方法,在调用者不知道任何细节的情况下可以进行安全的调用。当然,那个封装代价有点大了。

我作了如下修改:
1.定义一个抽象方法:
protected abstract object Execute(params object [] args);
这个方法才是真正需要继承的方法。
2.基类的Work方法改成私有方法(Work这个名字取得不是太好),代码这样写:
System.Threading.Thread.CurrentThread.IsBackground = true;
_workThread = System.Threading.Thread.CurrentThread;
return Execute(args);
3.加一个线程方法:
void start()
{
StartTask(new TaskDelegate(Work), tempArgs);
}
4.定义一个私有字段用来向线程传递参数:
private object[] tempArgs;
5.最后加一个启动方法:
public void Start(params object[] args)
{
tempArgs = args;
Thread thread = new Thread(new ThreadStart(start));
thread.Start();
}

改造完成了。客户端代码由此变得非常简洁:
1.当按下“开始执行”时的代码:
_Task.Start(new object[] {});
2.Concrete类型newasynchui的代码也简单了,只需要重写一个Execute方法而不是重载一个Work和另外写一个Work2,在方法中也不必调用base.Work,你想调用也调用不了,因为是那是私有方法。

当然还有其它一些更好的建议,例如不必定义那么多的事件,其实一两个就足够了,也不需要派生新的EventArgs类型,因为从sender中可以获得所有的信息。

我的解决方案可能更邪一点了,因为我是用反射和Emit实现的,原理和你的差不多,只不过客户端代码可以非常简单而已。
            
 218.81.143.* 2005-09-14 20:59  
谢谢,[双鱼座]评论.说得非常到位,很有价值:).
我想你的解决方案一定相当不错,能否Mail一份,学习探讨探讨.the8341 at gmail.com
            
  2005-09-19 11:19  
@net66:
呵呵,OK,这两天我整理一下也写篇文章和你分享。
            
 218.79.244.* 2005-09-19 11:36  
@双鱼座
:-) 好文共享,期待中
            
  2005-09-19 17:35  
我的文章已经写完:
            
 [楼主] 2005-09-20 09:10  
双鱼座的文章,作者功底颇深.
            
 222.82.56.* 2006-10-07 16:37 
看了例程非常激动,也许是还有很多东西要学没有看的很彻底,希望楼主能解释,就是在UI中启动一个辅助线程后往往会应为需要在UI启动的这个辅助线程中在启动其他线程,这个时候该怎样使用Task抽象类,该如何将辅助线程启动的其他线程中的信息显示在UI中,还有怎么才能利用AsynchThread 在UI中停止辅助线程的时候能同时停止辅助线程启动的其他线程,希望楼主能解答,谢谢!!
          
 58.241.234.* 2007-05-04 15:07 
文章写的不错,狂学习。
          
  2007-07-19 13:33  
谢谢楼主与双鱼座,我还有点问题,想清楚了再跟你们沟通
            
  2008-01-10 10:56  
非常经典!值得研究!
            
  2008-03-21 21:45  
谢谢,收藏了!
            
 222.20.100.* 2008-08-19 17:54 
下了,研究研究,谢谢啦。
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值