BackgroundWorker的使用

来源:互联网 发布:php curl发送post请求 编辑:程序博客网 时间:2024/04/27 21:31

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;
 }
 //...

原创粉丝点击