线程封装组件(BackgroundWorker)和线程(Thread)

      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的使用就非常简单:

 1         /// <summary>
 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已经不推荐使用。

 

  1        // 声明委托 
  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(0false== 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的使用就相对来说简单了。

 

 

posted @ 2009-11-20 14:57 萧萧空间 阅读(...) 评论(...) 编辑 收藏