BackgroundWorker是微軟的在.net Framwork中添加的一個組件,主要對線程的訪問提供了一種安全的方式。簡單的說就是對Thread的一次封裝。安全
BackgroundWorker位於System.ComponentModel下,是一個繼承了Component的組件,微軟官方的解釋爲:Executes an operation on a separate thread.就是說,開始一個新的線程執行操做。app
首先介紹一下BackgroundWorker的相關屬性和方法:異步
屬性:this
WorkerReportsProgress:是否能夠報告進度。spa
WorkerSupportsCancellation:是否容許異步停止。.net
IsBusy:是否在運行。線程
CancellationPending:判斷BackgroundWorker是否已經異步取消。code
方法:blog
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的使用就很是簡單:
/// <summary> /// Handles the Click event of the btnBackGroundWorker control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void btnBackGroundWorker_Click(object sender, EventArgs e) { StartFrom = Convert.ToInt32(txtStart.Text); EndTo = Convert.ToInt32(txtEnd.Text); progressBarThread.Minimum = StartFrom; progressBarThread.Maximum = EndTo; this.btnBackGroundWorker.Enabled = false; this.backgroundWorker.RunWorkerAsync(); } /// <summary> /// Handles the DoWork event of the backgroundWorker control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param> private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { for (int nValue = StartFrom; nValue <= EndTo; nValue++) { if (this.backgroundWorker.CancellationPending) { e.Cancel = true; return; } this.backgroundWorker.ReportProgress(nValue); Thread.Sleep(200); } } /// <summary> /// Handles the ProgressChanged event of the backgroundWorker control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param> private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.prgProcessBackGroundWorker.Value = e.ProgressPercentage; } /// <summary> /// Handles the RunWorkerCompleted event of the backgroundWorker control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param> private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // 取消 if (e.Cancelled) { MessageBox.Show("Cancelled"); } // 出現錯誤 else if (e.Error != null) { MessageBox.Show(e.Error.Message + Environment.NewLine + e.Error.StackTrace); } // 完成 else { MessageBox.Show("Completed"); this.btnBackGroundWorker.Enabled = true; } } /// <summary> /// Handles the Click event of the btnCancelBackgroundWoker control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void btnCancelBackgroundWoker_Click(object sender, EventArgs e) { this.backgroundWorker.CancelAsync(); }
Thread的使用就比較麻煩了,對於尤爲是對異步提醒來講,須要寫委託,代碼量是不少,可是對於BackgroundWorker來講,卻沒有線程暫停和繼續的方法。可是對於通常的來講,這些功能也是不用的,並且在微軟的文檔中還提到了,Thread的Resume和Suspend已經不推薦使用。
// 聲明委託 delegate void DelegateType(int x); DelegateType TheDelegate; // ProgressBar的開始和結束值 int StartFrom, EndTo; // 是否線程暫停 bool IsThreadPaused; ManualResetEvent CancelEvent = new ManualResetEvent(false); Thread MyThread; /// <summary> /// 委託的消息事件 /// </summary> /// <param name="nProgress">進度值</param> private void MessageHandler(int nProgress) { lblThreadStatus.Text = "處理: " + Convert.ToString(nProgress); progressBarThread.Value = nProgress; if (nProgress == progressBarThread.Maximum) { MessageBox.Show("Completed"); this.btnTread.Enabled = true; } } /// <summary> /// Handles the Click event of the btnTread control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void btnTread_Click(object sender, EventArgs e) { TheDelegate = MessageHandler; StartFrom = Convert.ToInt32(txtStart.Text); EndTo = Convert.ToInt32(txtEnd.Text); progressBarThread.Minimum = StartFrom; progressBarThread.Maximum = EndTo; btnTread.Enabled = false; IsThreadPaused = false; MyThread = new Thread(ProcessRoutine); MyThread.Start(); } /// <summary> /// Processes the routine. /// </summary> private void ProcessRoutine() { for (int nValue = StartFrom; nValue <= EndTo; nValue++) { // 判斷是否取消 if (CancelEvent.WaitOne(0, false) == true) { return; } this.BeginInvoke(this.TheDelegate, nValue); Thread.Sleep(200); } } /// <summary> /// Handles the Click event of the btnCancelThread control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void btnCancelThread_Click(object sender, EventArgs e) { btnCancelThread.Enabled = false; btnPauseThread.Enabled = false; CancelEvent.Set(); MyThread.Join(); } /// <summary> /// Handles the Click event of the btnPauseThread control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void btnPauseThread_Click(object sender, EventArgs e) { // Bad approach! if (!IsThreadPaused) { IsThreadPaused = true; MyThread.Suspend(); btnPauseThread.Text = "Resume Thread"; // Disallow Cancel btnCancelThread.Enabled = false; } else { IsThreadPaused = false; MyThread.Resume(); btnPauseThread.Text = "Pause Thread"; btnCancelThread.Enabled = true; } }
比較起來,兩個是徹底相同的,對於Thread來講,靈活性就比較好了,BackgroundWorker的使用就相對來講簡單了。