BackgroundWorker是微软的在.net Framwork中添加的一个组件,主要对线程的访问提供了一种安全的方式。简单的说就是对Thread的一次封装。
BackgroundWorker位于System.ComponentModel下,是一个继承了Component的组件,微软官方的解释为:Executes an operation on a separate thread.就是说,开始一个新的线程执行操作。
首先介绍一下BackgroundWorker的相关属性和方法:
属性:
WorkerReportsProgress:是否可以报告进度。
WorkerSupportsCancellation:是否允许异步中止。
IsBusy:是否在运行。
CancellationPending:判断BackgroundWorker是否已经异步取消。
方法:
RunWorkerAsync:开始执行任务。触发DoWork事件
ReportProgress:异步提醒,触发ProgressChanged事件,但是这个如果可以使用,必须设置WorkerReportsProgress为True
CancelAsync:取消BackgroundWorker操作。
事件:
DoWork:执行RunWorkerAsync后触发,异步执行的认为。
ProgressChanged:执行ReportProgress时触发,异步获得进度。
RunWorkerCompleted:线程结束时触发,主要有成功结束,发生异常或者取消时发生。
Thread相对来说就简单了,但是使用起来就比较麻烦了。Thread位于System.Threading的名空间下,是一个可以独立创建和操作一个线程,并且对线程进行设置优先级和获得状态的一个不可继承的类。
下面是我做的一个例子,来比较他们两个的使用。
建立一个窗体,放置了两个TextBox,分别为设置开始和结束的Progree的值,放置两个ProgressBar,分别设置为线程的Progressbar和BackGroundWorker的ProgressBar。另外放置按钮为StartBackGroundWorker,StartThread,CancelBackGroundWorker,CancelThread和PauseThread。
BackGroundWorker的使用就非常简单:
2 /// Handles the Click event of the btnBackGroundWorker control.
3 /// </summary>
4 /// <param name="sender"> The source of the event. </param>
5 /// <param name="e"> The <see cref="System.EventArgs"/> instance containing the event data. </param>
6 private void btnBackGroundWorker_Click( object sender, EventArgs e)
7 {
8 StartFrom = Convert.ToInt32(txtStart.Text);
9 EndTo = Convert.ToInt32(txtEnd.Text);
10
11 progressBarThread.Minimum = StartFrom;
12 progressBarThread.Maximum = EndTo;
13
14 this .btnBackGroundWorker.Enabled = false ;
15
16 this .backgroundWorker.RunWorkerAsync();
17 }
18
19 /// <summary>
20 /// Handles the DoWork event of the backgroundWorker control.
21 /// </summary>
22 /// <param name="sender"> The source of the event. </param>
23 /// <param name="e"> The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data. </param>
24 private void backgroundWorker_DoWork( object sender, DoWorkEventArgs e)
25 {
26 for ( int nValue = StartFrom; nValue <= EndTo; nValue ++ )
27 {
28 if ( this .backgroundWorker.CancellationPending)
29 {
30 e.Cancel = true ;
31 return ;
32 }
33 this .backgroundWorker.ReportProgress(nValue);
34 Thread.Sleep( 200 );
35 }
36 }
37
38 /// <summary>
39 /// Handles the ProgressChanged event of the backgroundWorker control.
40 /// </summary>
41 /// <param name="sender"> The source of the event. </param>
42 /// <param name="e"> The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data. </param>
43 private void backgroundWorker_ProgressChanged( object sender, ProgressChangedEventArgs e)
44 {
45 this .prgProcessBackGroundWorker.Value = e.ProgressPercentage;
46 }
47
48 /// <summary>
49 /// Handles the RunWorkerCompleted event of the backgroundWorker control.
50 /// </summary>
51 /// <param name="sender"> The source of the event. </param>
52 /// <param name="e"> The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data. </param>
53 private void backgroundWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e)
54 {
55 // 取消
56 if (e.Cancelled)
57 {
58 MessageBox.Show( " Cancelled " );
59 }
60 // 出现错误
61 else if (e.Error != null )
62 {
63 MessageBox.Show(e.Error.Message + Environment.NewLine + e.Error.StackTrace);
64 }
65 // 完成
66 else
67 {
68 MessageBox.Show( " Completed " );
69 this .btnBackGroundWorker.Enabled = true ;
70 }
71 }
72
73 /// <summary>
74 /// Handles the Click event of the btnCancelBackgroundWoker control.
75 /// </summary>
76 /// <param name="sender"> The source of the event. </param>
77 /// <param name="e"> The <see cref="System.EventArgs"/> instance containing the event data. </param>
78 private void btnCancelBackgroundWoker_Click( object sender, EventArgs e)
79 {
80 this .backgroundWorker.CancelAsync();
81 }
Thread的使用就比较麻烦了,对于尤其是对异步提醒来说,需要写委托,代码量是很多,但是对于BackgroundWorker来说,却没有线程暂停和继续的方法。但是对于一般的来说,这些功能也是不用的,而且在微软的文档中还提到了,Thread的Resume和Suspend已经不推荐使用。
2 delegate void DelegateType( int x);
3 DelegateType TheDelegate;
4
5 // ProgressBar的开始和结束值
6 int StartFrom, EndTo;
7
8 // 是否线程暂停
9 bool IsThreadPaused;
10
11 ManualResetEvent CancelEvent = new ManualResetEvent( false );
12 Thread MyThread;
13
14 /// <summary>
15 /// 委托的消息事件
16 /// </summary>
17 /// <param name="nProgress"> 进度值 </param>
18 private void MessageHandler( int nProgress)
19 {
20 lblThreadStatus.Text = " 处理: " + Convert.ToString(nProgress);
21 progressBarThread.Value = nProgress;
22
23 if (nProgress == progressBarThread.Maximum)
24 {
25 MessageBox.Show( " Completed " );
26 this .btnTread.Enabled = true ;
27 }
28 }
29
30 /// <summary>
31 /// Handles the Click event of the btnTread control.
32 /// </summary>
33 /// <param name="sender"> The source of the event. </param>
34 /// <param name="e"> The <see cref="System.EventArgs"/> instance containing the event data. </param>
35 private void btnTread_Click( object sender, EventArgs e)
36 {
37 TheDelegate = MessageHandler;
38
39 StartFrom = Convert.ToInt32(txtStart.Text);
40 EndTo = Convert.ToInt32(txtEnd.Text);
41
42 progressBarThread.Minimum = StartFrom;
43 progressBarThread.Maximum = EndTo;
44
45 btnTread.Enabled = false ;
46
47 IsThreadPaused = false ;
48 MyThread = new Thread(ProcessRoutine);
49 MyThread.Start();
50 }
51
52 /// <summary>
53 /// Processes the routine.
54 /// </summary>
55 private void ProcessRoutine()
56 {
57 for ( int nValue = StartFrom; nValue <= EndTo; nValue ++ )
58 {
59 // 判断是否取消
60 if (CancelEvent.WaitOne( 0 , false ) == true )
61 {
62 return ;
63 }
64 this .BeginInvoke( this .TheDelegate, nValue);
65 Thread.Sleep( 200 );
66 }
67 }
68
69 /// <summary>
70 /// Handles the Click event of the btnCancelThread control.
71 /// </summary>
72 /// <param name="sender"> The source of the event. </param>
73 /// <param name="e"> The <see cref="System.EventArgs"/> instance containing the event data. </param>
74 private void btnCancelThread_Click( object sender, EventArgs e)
75 {
76 btnCancelThread.Enabled = false ;
77 btnPauseThread.Enabled = false ;
78
79 CancelEvent.Set();
80 MyThread.Join();
81 }
82
83 /// <summary>
84 /// Handles the Click event of the btnPauseThread control.
85 /// </summary>
86 /// <param name="sender"> The source of the event. </param>
87 /// <param name="e"> The <see cref="System.EventArgs"/> instance containing the event data. </param>
88 private void btnPauseThread_Click( object sender, EventArgs e)
89 {
90 // Bad approach!
91 if ( ! IsThreadPaused)
92 {
93 IsThreadPaused = true ;
94 MyThread.Suspend();
95 btnPauseThread.Text = " Resume Thread " ;
96
97 // Disallow Cancel
98 btnCancelThread.Enabled = false ;
99 }
100 else
101 {
102 IsThreadPaused = false ;
103 MyThread.Resume();
104 btnPauseThread.Text = " Pause Thread " ;
105 btnCancelThread.Enabled = true ;
106 }
107 }
108
比较起来,两个是完全相同的,对于Thread来说,灵活性就比较好了,BackgroundWorker的使用就相对来说简单了。