一、引言
     在编写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 )方便调用。在实际使用时,可在继承类中定义多个相同调用接口的方法,避免重复编码,较为方便。

给大家作个参考,而大牛呢,多点指正。当是扔个砖头,想砸块玉吧。

二、代码

  1using System;
  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        } 
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        /**//// <summary>
212        /// 任务调用线程(前台或UI线程)
213        /// </summary>
214        public System.Threading.Thread CallThread
215        {
216            get { return _callThread;}
217        }
218        /**//// <summary>
219        /// 任务工作线程(后台)
220        /// </summary>
221        public System.Threading.Thread WordThread
222        {
223            get {return _workThread;}
224        }
225        
226        /**//// <summary>
227        /// 任务进度(0-100)
228        /// </summary>
229        public int Progress
230        {
231            get {return _progress;} 
232        }
233        /**//// <summary>
234        /// 任务工作状态
235        /// </summary>
236        public TaskStatus TaskState
237        {
238            get {return _taskState;}
239        }
240        /**//// <summary>
241        /// 任务工作结果
242        /// </summary>
243        public object Result
244        {
245            get {return _result;}
246        }
247
248        protected bool IsStop
249        {
250            get
251            {
252                bool result = false;
253                switch (_taskState)
254                {
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
268        触发事件#region 触发事件
269        /**//// <summary>
270        /// 触发任务工作状态变化事件
271        /// </summary>
272        /// <param name="status">任务工作状态</param>
273        /// <param name="result">任务工作结果对象</param>
274        protected void FireStatusChangedEvent(TaskStatus status, object result) 
275        
276            if( TaskStatusChanged != null ) 
277            
278                TaskEventArgs args = new TaskEventArgs( status,result); 
279                AsyncInvoke(TaskStatusChanged,args);
280            } 
281        } 
282 
283        /**//// <summary>
284        /// 触发任务进度变化事件
285        /// </summary>
286        /// <param name="progress">任务进度(0-100)</param>
287        /// <param name="result">任务工作中间结果对象</param>
288        protected void FireProgressChangedEvent(int progress, object result) 
289        
290            if( TaskProgressChanged != null ) 
291            
292                TaskEventArgs args = new TaskEventArgs( progress,result); 
293                AsyncInvoke(TaskProgressChanged,args);
294            } 
295        } 
296        /**//// <summary>
297        /// 触发工作方法执行中发现错误事件
298        /// </summary>
299        /// <param name="progress">任务进度(0-100)</param>
300        /// <param name="result">任务工作中间结果对象</param>
301        protected void FireThrowErrorEvent(int progress, object result) 
302        
303            if( TaskThrowError != null ) 
304            
305                TaskEventArgs args = new TaskEventArgs( progress,result); 
306                AsyncInvoke(TaskThrowError,args);
307            } 
308        } 
309        /**//// <summary>
310        /// 触发被调用者取消事件
311        /// </summary>
312        /// <param name="progress">任务进度(0-100)</param>
313        /// <param name="result">任务工作中间结果对象</param>
314        protected void FireCancelEvent(int progress, object result) 
315        
316            if( TaskCancel != null ) 
317            
318                TaskEventArgs args = new TaskEventArgs( progress,result); 
319                AsyncInvoke(TaskCancel,args);
320            } 
321        } 
322        /**//// <summary>
323        /// 触发被调用者强行中止事件
324        /// </summary>
325        /// <param name="progress">任务进度(0-100)</param>
326        /// <param name="result">任务工作中间结果对象</param>
327        protected void FireAbortEvent(int progress, object result) 
328        
329            if( TaskAbort != null ) 
330            
331                TaskEventArgs args = new TaskEventArgs( progress,result); 
332                AsyncInvoke(TaskAbort,args);
333            } 
334        } 
335        /**//// <summary>
336        /// 异步调用挂接事件委托
337        /// </summary>
338        /// <param name="eventhandler">事件处理方法句柄</param>
339        /// <param name="args">事件消息</param>
340        protected void AsyncInvoke(TaskEventHandler eventhandler,TaskEventArgs args)
341        {
342//            TaskEventHandler[] tpcs = (TaskEventHandler[])eventhandler.GetInvocationList();
343            Delegate[] tpcs = eventhandler.GetInvocationList();
344            foreach(TaskEventHandler tpc in tpcs)
345            {
346                if ( tpc.Target is System.Windows.Forms.Control ) 
347                
348                    Control targetForm = tpc.Target as System.Windows.Forms.Control; 
349                    targetForm.BeginInvoke( tpc,new object[] { this, args } ); 
350                } 
351                else 
352                
353                    tpc.BeginInvoke(this, args ,null,null); //异步调用,启动后不管
354                }
355            }        
356        }
357        #endregion
358
359        工作进程管理#region 工作进程管理
360        /**//// <summary>
361        /// 开启任务默认的工作进程
362        /// [public object Work(params  object[] args )]
363        /// </summary>
364        /// <param name="args">传入的参数数组</param>
365        public bool StartTask( params object[] args ) 
366        
367            return StartTask(new TaskDelegate( Work ),args); 
368        } 
369        /**//// <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 ) 
376        
377            bool result =false;
378            lock( this ) 
379            
380                if( IsStop && worker != null ) 
381                
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        } 
395        /**//// <summary>
396        /// 请求停止任务进程
397        /// 是否停止成功,应看任务工作状态属性TaskState是否为TaskStatus.Stop
398        /// </summary>
399        public bool StopTask() 
400        
401            bool result =false;
402            lock( this ) 
403            
404                if( _taskState == TaskStatus.Running ) 
405                
406                    // 更新任务工作状态 
407                    _taskState = TaskStatus.CancelPending; 
408                    // 触发任务工作状态变化事件
409                    FireStatusChangedEvent( _taskState, _result); 
410                    result = true;
411                } 
412            } 
413            return result;
414        } 
415        /**//// <summary>
416        /// 强行中止任务的工作线程
417        /// 
418        /// </summary>
419        public bool AbortTask() 
420        
421            bool result = false;
422            lock( this ) 
423            
424                if( _taskState == TaskStatus.Running && _workThread != null ) 
425                
426                    if (_workThread.ThreadState != System.Threading.ThreadState.Stopped)
427                    {
428                        _workThread.Abort();
429                    }
430                    System.Threading.Thread.Sleep(2);
431                    if (_workThread.ThreadState == System.Threading.ThreadState.Stopped)
432                    {
433                        // 更新任务工作状态 
434                        _taskState = TaskStatus.Aborted; 
435                        result = true;
436                    }
437                    else
438                    {
439                        // 更新任务工作状态 
440                        _taskState = TaskStatus.AbortPending; 
441                        result = false;
442                    }
443                    // 触发任务工作状态变化事件
444                    FireStatusChangedEvent( _taskState, _result); 
445                } 
446            } 
447            return result;
448        } 
449
450        /**//// <summary>
451        /// 工作方法完成后的回调方法
452        /// 将检查是否出错,并获取、更新返回结果值
453        /// </summary>
454        /// <param name="ar">异步调用信号对象</param>
455        protected void EndWorkBack( IAsyncResult ar ) 
456        
457            bool error = false;
458            bool abort = false;
459            try                                                //检查是否错误
460            {
461                TaskDelegate del = (TaskDelegate)ar.AsyncState; 
462                _result = del.EndInvoke( ar ); 
463            }
464            catch(Exception e)                                //如果错误,则保存错误对象
465            {
466                error = true;
467                _exception = e;
468                if (e.GetType() == typeof(System.Threading.ThreadAbortException))
469                {
470                    abort = true;
471                    FireAbortEvent(_progress,_exception);
472                }
473                else
474                {
475                    FireThrowErrorEvent(_progress,_exception);
476                }
477            }
478            lock( this ) 
479            
480                if (error)
481                {
482                    if ( abort)
483                    {
484                        _taskState = TaskStatus.Aborted;        //调用者强行中止
485                    }
486                    else
487                    {
488                        _taskState = TaskStatus.ThrowErrorStoped;//出现错误而中止
489                    }
490                } 
491                else
492                {    _taskState = TaskStatus.Stopped;}          //正常结束
493                FireStatusChangedEvent( _taskState, _result);
494            } 
495        } 
496        #endregion
497
498        工作方法的基础#region 工作方法的基础
499        /**//// <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 )
512        {
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使用Task类#region 使用Task类
524/**//*
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

示例代码下载

转载于:https://www.cnblogs.com/zhoufleru/archive/2007/09/14/892641.html

衔接UI线程和管理后台工作线程的类(多线程、异步调用)[转]相关推荐

  1. 技术派-在工作线程与UI线程中创建对话框

    目录 UI线程创建方式 头文件模板 实现代码模板 工作线程的创建方式 工作线程的线程模板 对话框头文件模板 对话框实现部分 我们在工作中,经常需要在新线程里面创建对话框,要么是在工作线程里面创建对话框 ...

  2. 线程池是怎样工作的?

    来源:逅弈逐码(ID:CodeChaaaser) 我们在工作中或多或少都使用过线程池,但是为什么要使用线程池呢?从他的名字中我们就应该知道,线程池使用了一种池化技术,和很多其他池化技术一样,都是为了更 ...

  3. Mirror--镜像使用的工作线程数

    /* 在SQL SERVER 2005 及以后版本中, 使用'MAXworker thread' 来配置 可用的线程数,默认设置为0 ,即自动控制线程数   计算最大工作线程数:   对于32 位系统 ...

  4. nodejs 工作线程的基本使用(worker_threads)

    目录 前言 主线程与工作线程 工作线程交互 尾言 前言 nodejs从第十版开始,支持了真正的多线程编程,今天我们就来学习一下worker_threads工作线程的一些基本使用方法. 主线程与工作线程 ...

  5. Linux基础——后台工作和程序管理

    后台工作和程序管理 后台工作和程序是什么? 父程序和子程序 后台工作 后台运行--& 丢到后台暂停--Ctrl+z 观察当前后台工作--jobs 将后台工作转为前台运行--fg 让后台工作运行 ...

  6. C#中的多线程-线程同步基础 (控制线程数量)

    同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具: 简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程完成 锁系统 构成 目的 跨进程? 速度 loc ...

  7. java 线程 通过interrupted_分析Java线程中断机制stop和interrupted的用法

    1.引言当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时--都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法来停 ...

  8. 【转】ABP源码分析九:后台工作任务

    文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob).ABP通过BackgroundWorkerManager来管理Backgr ...

  9. 一文详解java线程池 详解Java线程池的七个参数 详解池化技术 java如何选择核心线程数 详解Java线程池的拒绝策略

    目录 引言 线程池使用场景 加快请求响应(响应时间优先) 加快处理大任务(吞吐量优先) 特殊说明 线程池的池化技术 线程池的创建 手动创建 创建newFixedThreadPool线程池 创建newS ...

最新文章

  1. tftp服务器_Transfer for Mac(TFTP服务器)
  2. 纯javascript实现pdf签名_Mac最强PDF编辑工具
  3. apache证书不受信任_苹果iOS手动安装和信任企业级应用
  4. 山海伏妖录java_山海伏妖录攻略大全 剧情结局加点妖兽大全
  5. Java中什么时候throws_何时在Java方法声明中使用throws?
  6. 华为系统p40pro计算机,华为P40 Pro:我来了!
  7. 关于SimpleDateFormat的一些使用及性能数据
  8. android关联发送程序,Android Handler机制之Message的发送与取出
  9. 努比亚更新系统服务器,努比亚N3升级更新V2.11官方最新完整rom包
  10. echarts-python数据可视化大屏展示
  11. python计算两个矩形的重叠_用Python检查两个矩形是否重叠的程序
  12. 网页效果图设计之色彩配色索引
  13. data在python_Fake data的使用和产生 - Python篇
  14. 香港美食(3)——源记喳咋
  15. IE低版本提示下载新的浏览器js--IEOutTips.zip
  16. strchr()函数与strrchr()函数的实现
  17. LeetCode 448.找到所有数组中消失的数字
  18. 关于期刊审稿与同行评审,论文“不为所知”的拒稿秘密在这里
  19. 抓取微信群聊人数,并保存到excel表格
  20. C++中 对》和《的重载

热门文章

  1. 春节后赚钱风口在哪?
  2. 培养你的“翁格玛丽”
  3. 你用python做过哪些好玩的事情?
  4. Failed building wheel for scandir 解决方案
  5. OpenCV绘制线、矩形、圆等基本几何形状
  6. sql replace函数_SQL REPLACE函数概述
  7. ssis 包部署_如何使用各种选项从SSIS目录执行已部署的程序包
  8. Oracle :备份 、还原数据库
  9. matlab之中文字体乱码处理
  10. [转载] .NET 中可以有类似 JVM 的幻像引用吗?