2013年9月10日 星期二

[轉貼] 使用BackgroundWorker背景執行

出處:http://blog.tonycube.com/2011/04/backgroundworker.html

要寫背景執行程式,可以自己寫多執行緒來處理。如果需求不複雜,在.Net中可以使用BackgroundWorker來處理。會用到背景執行,是為了讓程式在執行長時間的運算時,不要讓使用者界面看起來像是當機一樣停止不動。

1.使用方法
  • RunWorkerAsync()方法:啟動背景執行時呼叫。
  • CancelAsync()方法:取消背景執行。
  • ReportProgress()方法:在DoWork事件處理函式中,送出進度報告,會被ProgressChanged事件接收。
  • DoWork事件:要在背景作業的程式放在DoWork事件的處理函式裡。需注意的是,在DoWork事件的處理函式裡不能有任何和UI元件的互動。
  • ProgressChanged事件:處理進度的顯示。可以和UI元件互動。
  • RunWorkerCompleted事件:執行完成。可以和UI元件互動。
  • WorkerReportsProgress屬性:設定是否可以接收進度報告。
  • WorkerSupportsCancellation屬性:設定是否支援非同步取消。
  • CancellationPending屬性:在DoWork事件處理函式裡,用來判斷是否有要求取消背景執行。
  • IsBusy屬性:在啟動背景作業之前,用來檢查是否仍有在執行的背景作業。

建立BackgroundWorker物件後,加入事件DoWork、ProgressChanged、RunWorkerCompleted,若要允許傳送處理進度,則WorkerReportsProgress屬性要設為true,若要允許背景執行程式可以中途被中斷,則WorkerSupportsCancellation要設為true。

當你要啟動背景執行時,例如按下按鈕就啟動背景執行作業,那就是在按鈕裡呼叫RunWorkerAsync()來啟動,你的BackgroundWorker物件的DoWork事件會收到事件觸發而執行DoWork事件處理函式中的程式。

在DoWork事件處理函式中的程式會一直執行直到結束,在執行期間可以呼叫ReportProgress()方法來送出處理進度,ProgressChanged事件會收到觸發而執行該處理函式裡的程式,例如改變ProgressBar的進度值。

當DoWork事件處理函式中的程式執行完畢,就會觸發RunWorkerCompleted事件。你也可以在DoWork事件中加入CancellationPending屬性的判斷,當使用者按下取消(也就是呼叫CancelAsync()方法)時,CancellationPending屬性會被設為false,你就可以強制DoWork處理函式中的程式結束。

另外,當你要啟動背景執行之前,可以用IsBusy屬性來判斷,該背景執行程式是否仍在執行中。

2.範例程式碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace BackgroundWorkerDemo
{
public partial class Form1 : Form
{
private BackgroundWorker bw;

public Form1()
{
InitializeComponent();

initProgressBar();
initBackgroundWorker();
}

private void initProgressBar()
{
progressBar1.Step = 1;
}

private void initBackgroundWorker()
{
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

}

//背景執行
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; (i <= 10); i++)
{
if ((bw.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// 使用sleep模擬運算時的停頓
System.Threading.Thread.Sleep(500);
bw.ReportProgress((i * 10));
}
}
}

//處理進度
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
this.lblMsg.Text = e.ProgressPercentage.ToString();
}

//執行完成
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{

if ((e.Cancelled == true))
{
this.lblMsg.Text = "取消!";
}

else if (!(e.Error == null))
{
this.lblMsg.Text = ("Error: " + e.Error.Message);
}

else
{
this.lblMsg.Text = "完成!";
}
}

private void btnStart_Click(object sender, EventArgs e)
{
if (bw.IsBusy != true)
{
this.lblMsg.Text = "開始";
this.progressBar1.Value = 0;
bw.RunWorkerAsync();
}
}

private void btnFinish_Click(object sender, EventArgs e)
{
if (bw.WorkerSupportsCancellation == true)
{
bw.CancelAsync();
}
}

}
}

3.參考資源

沒有留言:

張貼留言