BackgroundWorker的使用
如果讓我自已做一個顯示進度的程序,該怎么做?首先,定義一個委托,并調用BeginInvoke异步執行它,在執行結束后一定要調用EndInvoke.第二,在工作線程中更新界面進度時,要用Control.BeginInvoke.
void calcButton_Click(object sender,EventArgs e)
{
//啟用工作線程,并傳參到工作線程
this.backgroundWorker.RunWorkerAsync((int)this.decimalPlacesNumericUpDown.Value);
}
void backgroundWorker_DoWork(object sender,DoWorkEventArgs e)
{
//利用從UI中傳遞過來的參數
int digits=(int)e.Argument;
DateTime start=DateTime.Now;
//開始一段費時的操作
StringBuilder pi=new StringBuilder("3",digits+2);
//准備顯示進度
ShowProgressDelegate showProgress=new ShowProgressDelegate(ShowProgress);
//當需要回顯消息時,就調用
//報知進度,并將參數傳給ReportProgress事件
this.backgroundWorker.ReportProgress(0,new CalcPiUserState(pi.ToString(),digits,0));
if(digits>0)
{
pi.Append(".");
for(int i=0;i<digits;i+=9)
{
//...對數据的處理,這是一段耗時的代碼
//報知進度,并將參數傳給ReportProgress事件
this.backgroundWorker.ReportProgress(0,new CalcPiUserState(pi.ToString(),digits,i+digitCount));
}
}
//費時操作結束,返回總用時長
DateTime end=DateTime.Now;
TimeSpan elapsed=end-start;
//將參數傳給RunWorkerCompleted事件
e.Result=elapsed;
}
class CalcPiUserState
{
public readonly string Pi;
public readonly int TotalDigits;
public readonly int DigitsSoFar;
public CalcPiUserState(string pi,int totalDigits,int digitsSoFar)
{
this.Pi=pi;
this.TotalDigits=totalDigits;
this.DigitsSoFar=digitsSoFar;
}
}
void backgroundWorker_ProgressChanged(object sender,ProgressChangedEventArgs e)
{
CalcPiUserState progress=(CalcPiUserState)e.UserState;
//...這里寫与UI交互的代碼
}
void backgroundWorker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
//...這里寫与UI交互的代碼
//顯示耗時
TimeSpan elapsed=(TimeSpan)e.Result;
MessageBox.Show("Elasped:"+elapsed.ToString());
}
2.异常處理
如果發生异常,則會立即執行RunWorkerCompleted,所以應該在這里改.
void backgroundWorker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
if(e.Error!=null)
{
//...這里寫与UI交互的代碼
//如果發生异常,則提前終止工作線程
return;
}
}
3.取消
首先要提供一個界面供用戶操作.一般的操作界面如下:
(1)在計算過程開始后,將Calculate按鈕變成Cancel按鈕.并提供一個進度條
(2)打開一個單獨的進度對話框來顯示進度.
下面以第(1)种情況為例,需將calcButton_Click改成如下:
void calcButton_Click(object sender,EventArgs e)
{
//如果正在取消,則返回
if(this.backgroundWorker.CancellationPending) return;
//如果工作線程正在執行,則通知結束它
if(this.backgroundWorder.IsBusy)
{
this.calcButton.Enabled=false;
this.backgroundWorder.CancelAsync();
return;
}
//設置計算過程中的界面
this.calcButton.Text="Cancel";
this.calcTooStripProgressBar.Visible=true;
this.calcToolStripStatusLabel.Text="Calculating...";
//開始异步計算
this.backgroundWorder.RunWorkerAsync((int)this.decimalPlacesNumericUpDown.Value);
}
還需要
void backgroundWorker_DoWork(object sender,DoWorkEventArgs e)
{
//...
//判斷取消
if(this.backgroundWorker.CancellationPending)
{
e.Cancel=true;
}
//...
}
void backgroundWorker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
//...
//工作線程是否已取消
if(e.Cancelled)
{
this.resultTextBox.Text="Calculate";
return;
}
//...
}