程式碼
BackgroundWorker組件
在VS2005中添加了BackgroundWorker組件,該組件在多線程編程方面使用起來非常方便,然而在開始時由於沒有搞清楚它的使用機制,走了不少的彎路,現在把我在使用它的過程中的經驗與諸位分享一下。
BackgroundWorker類中主要用到的有這列屬性、方法和事件:
重要屬性:
1、CancellationPending 擷取一個值,指示應用程式是否已請求取消後台操作。通過在DoWork事件中判斷CancellationPending屬性可以認定是否需要取消後台操作(也就是結束線程);
2、IsBusy 擷取一個值,指示 BackgroundWorker 是否正在運行非同步作業。程式中使用IsBusy屬性用來確定後台操作是否正在使用中;
3、WorkerReportsProgress 擷取或設定一個值,該值指示BackgroundWorker能否報告進度更新
4、WorkerSupportsCancellation 擷取或設定一個值,該值指示 BackgroundWorker 是否支援非同步取消。設定WorkerSupportsCancellation為true使得程式可以調用CancelAsync方法提交終止掛起的後台操作的請求;
重要方法:
1、CancelAsync 請求取消掛起的後台操作
2、RunWorkerAsync 開始執行後台操作
3、ReportProgress 引發ProgressChanged事件
重要事件:
1、DoWork 調用 RunWorkerAsync 時發生
2、ProgressChanged 調用 ReportProgress 時發生
3、RunWorkerCompleted 當後台操作已完成、被取消或引發異常時發生
另外還有三個重要的參數是RunWorkerCompletedEventArgs以及DoWorkEventArgs、ProgressChangedEventArgs。
BackgroundWorker的各屬性、方法、事件的調用機制和順序:
從可見在整個生活周期內發生了3次重要的參數傳遞過程:
參數傳遞1:此次的參數傳遞是將RunWorkerAsync(Object)中的Object傳遞到DoWork事件的DoWorkEventArgs.Argument,由於在這裡只有一個參數可以傳遞,所以在實際應用往封裝一個類,將整個執行個體化的類作為RunWorkerAsync的Object傳遞到DoWorkEventArgs.Argument;
參數傳遞2:此次是將程式運行進度傳遞給ProgressChanged事件,實際使用中往往使用給方法和事件更新進度條或者日誌資訊;
參數傳遞3:在DoWork事件結束之前,將後台線程產生的結果資料賦給DoWorkEventArgs.Result一邊在RunWorkerCompleted事件中調用RunWorkerCompletedEventArgs.Result屬性取得後台線程產生的結果。
另外從可以看到DoWork事件是在後台線程中啟動並執行,所以在該事件中不能夠操作使用者介面的內容,如果需要更新使用者介面,可以使用ProgressChanged事件及RunWorkCompleted事件來實現。
在WinForm中經常遇到一些費時的操作介面,比如統計某個磁碟分割的檔案夾或者檔案數目,如果分區很大或者檔案過多的話,處理不好就會造成“假死”的情況,或者報“線程間操作無效”的異常,為瞭解決這個問題,可以使用委託來處理,在.net2.0中還可以用BackgroundWorker類。
BackgroundWorker類是.net 2.0裡新增加的一個類,對於需要長時間操作而不需要使用者長時間等待的情況可以使用這個類。
注意確保在 DoWork 事件處理常式中不操作任何使用介面物件。而應該通過 ProgressChanged 和 RunWorkerCompleted 事件與使用者介面進行通訊。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
/*
* 作者:周公
* BackgroundWorker類是.net 2.0裡新增加的一個類,對於需要長時間操作而不需要使用者長時間等待的情況可以使用這個類。
* 注意確保在 DoWork 事件處理常式中不操作任何使用介面物件。而應該通過 ProgressChanged 和 RunWorkerCompleted 事件與使用者介面進行通訊。
* 它有幾個屬性:
* CancellationPending——指示應用程式是否已請求取消後台操作。
* IsBusy——指示 BackgroundWorker 是否正在運行非同步作業
* WorkerReportsProgress——該值指示 BackgroundWorker 能否報告進度更新
* WorkerSupportsCancellation——該值指示 BackgroundWorker 是否支援非同步取消
* 還有如下事件:
* DoWork——調用 RunWorkerAsync 時發生。
* ProgressChanged——調用 ReportProgress 時發生。
* RunWorkerCompleted——當後台操作已完成、被取消或引發異常時發生。
*
* 還有如下方法:
* CancelAsync——請求取消掛起的後台操作
* ReportProgress——引發 ProgressChanged 事件
* RunWorkerAsync——開始執行後台操作
*
**/
namespace BackgroundWorkerDemo
{
public partial class MainForm : Form
{
private BackgroundWorker worker = new BackgroundWorker();
public MainForm()
{
InitializeComponent();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
//正式做事情的地方
worker.DoWork+=new DoWorkEventHandler(DoWork);
//任務完稱時要做的,比如提示等等
worker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
//任務進行時,報告進度
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);
}
//調用 RunWorkerAsync 時發生
public void DoWork(object sender, DoWorkEventArgs e)
{
e.Result = ComputeFibonacci(worker, e);//當ComputeFibonacci(worker, e)返回時,非同步過程結束
}
//調用 ReportProgress 時發生
public void ProgessChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
//當後台操作已完成、被取消或引發異常時發生
public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("完成!");
}
private int ComputeFibonacci(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 1000; i++)
{
if (worker.CancellationPending)
{
e.Cancel = true;
}
else
{
worker.ReportProgress(i);
}
System.Threading.Thread.Sleep(10);
}
return -1;
}
private void btnStart_Click(object sender, EventArgs e)
{
worker.RunWorkerAsync();
btnStart.Enabled = false;
btnPause.Enabled = true;
}
private void btnPause_Click(object sender, EventArgs e)
{
btnPause.Enabled = false;
btnStart.Enabled = true;
worker.CancelAsync();
}
}
}
http://www.qimao.cn/article.asp?id=168