标题：BackgroundWorker
DoWork 事件
//以C++为例（现在C++.net的书比较少，所以照顾一下，都以C++为例。不过其它语言的也可以看，差不太多）
void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
其中句柄sender指向的就是该BackgroundWorker控件。
第二个参数e有三个属性，Argument,Cancel和Result。
Argument:
大家应该还记得如何触发DoWork事件吧？对了，就是在程序中调用RunWorkerAsync方法，RunWorkerAsync方法有两种重载，第一种是无参形式，第二种是有一个指向Object^类型的参数，如果你调用的是有参类型的RunWorkerAsync,则DoWork事件处理程序的第二个参数e的Argment属性将会返回一个指向你传递过来的这个参数。
Cancel:
DoWork 事件处理程序中的代码应定期检查 CancellationPending属性值，并在该值为 true 时中止操作。出现这种情况时，可以将 System.ComponentModel.DoWorkEventArgs 的 Cancel标志设置为 true，同时将 RunWorkerCompleted 事件处理程序中的 System.ComponentModel.RunWorkerCompletedEventArgs的 Cancelled 标志设置为 true。
Result:
等下面讲到RunWorkerCompleted事件时再细说。
RunWorkerCompleted事件
当DoWork事件处理完成之后，将会触发该事件。
void backgroundWorker1_RunWorkerCompleted( Object^ sender, RunWorkerCompletedEventArgs^ e )
现在主要讲第二个参数e,最重要的属性是Result。
在DoWork事件中，你将Result设置成什么，这里的Result就返回什么。
ProgressChanged事件
在DoWork事件的处理过程中，如果调用ReportProgress则会发生该事件。
void backgroundWorker1_ProgressChanged( Object^ sender, ProgressChangedEventArgs^ e )
先来说说ReportProgress的两种重载：
void ReportProgress(int percentProgress)
void ReportProgress(int percentProgress,Object^ userState)
ProgressChanged事件处理程序的第二个参数e有一个ProgressPercentage属性，它就由ReportProgress的第一个参数percentProgress来提供。这个参数一般用来报告该后台操作完成的进度，然后用ProgressChanged的第二个参数e的ProgressPercentage属性来获取该进度信息。如果用户还想传递更多的信息，可以使用ReportProgress的第二种重载，它的第二个参数userState将会传递给ProgressChanged事件的参数e的UserState属性。
好，下面来一段MSDN上的例子：
示例代码：
以C++为例
#using <System.Drawing.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Threading;
using namespace System::Windows::Forms;
public ref class FibonacciForm: public System::Windows::Forms::Form
{
private:
int numberToCompute;
int highestPercentageReached;
System::Windows::Forms::NumericUpDown^ numericUpDown1;
System::Windows::Forms::Button^ startAsyncButton;
System::Windows::Forms::Button^ cancelAsyncButton;
System::Windows::Forms::ProgressBar^ progressBar1;
System::Windows::Forms::Label ^ resultLabel;
System::ComponentModel::BackgroundWorker^ backgroundWorker1;
public:
FibonacciForm()
{
InitializeComponent();
numberToCompute = highestPercentageReached = 0;
InitializeBackgoundWorker();
}
private:
// Set up the BackgroundWorker object by 
// attaching event handlers. 
void InitializeBackgoundWorker()
{
backgroundWorker1->DoWork += gcnew DoWorkEventHandler( this, &FibonacciForm::backgroundWorker1_DoWork );
backgroundWorker1->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &FibonacciForm::backgroundWorker1_RunWorkerCompleted );
backgroundWorker1->ProgressChanged += gcnew ProgressChangedEventHandler( this, &FibonacciForm::backgroundWorker1_ProgressChanged );
}
void startAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
{
// Reset the text in the result label.
resultLabel->Text = String::Empty;
// Disable the UpDown control until 
// the asynchronous operation is done.
this->numericUpDown1->Enabled = false;
// Disable the Start button until 
// the asynchronous operation is done.
this->startAsyncButton->Enabled = false;
// Enable the Cancel button while 
// the asynchronous operation runs.
this->cancelAsyncButton->Enabled = true;
// Get the value from the UpDown control.
numberToCompute = (int)numericUpDown1->Value;
// Reset the variable for percentage tracking.
highestPercentageReached = 0;
// Start the asynchronous operation.
backgroundWorker1->RunWorkerAsync( numberToCompute );
}
void cancelAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
{ 
// Cancel the asynchronous operation.
this->backgroundWorker1->CancelAsync();
// Disable the Cancel button.
cancelAsyncButton->Enabled = false;
}
// This event handler is where the actual,
// potentially time-consuming work is done.
void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the 
// RunWorkerCompleted eventhandler.
e->Result = ComputeFibonacci( safe_cast<Int32>(e->Argument), worker, e );
}
// This event handler deals with the results of the
// background operation.
void backgroundWorker1_RunWorkerCompleted( Object^ /*sender*/, RunWorkerCompletedEventArgs^ e )
{
// First, handle the case where an exception was thrown.
if ( e->Error != nullptr )
{
MessageBox::Show( e->Error->Message );
}
else
if ( e->Cancelled )
{
// Next, handle the case where the user cancelled 
// the operation.
// Note that due to a race condition in 
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
resultLabel->Text = "Cancelled";
}
else
{
// Finally, handle the case where the operation 
// succeeded.
resultLabel->Text = e->Result->ToString();
}
// Enable the UpDown control.
this->numericUpDown1->Enabled = true;
// Enable the Start button.
startAsyncButton->Enabled = true;
// Disable the Cancel button.
cancelAsyncButton->Enabled = false;
}
// This event handler updates the progress bar.
void backgroundWorker1_ProgressChanged( Object^ /*sender*/, ProgressChangedEventArgs^ e )
{
this->progressBar1->Value = e->ProgressPercentage;
}
// This is the method that does the actual work. For this
// example, it computes a Fibonacci number and
// reports progress as it does its work.
long ComputeFibonacci( int n, BackgroundWorker^ worker, DoWorkEventArgs ^ e )
{
// The parameter n must be >= 0 and <= 91.
// Fib(n), with n > 91, overflows a long.
if ( (n < 0) || (n > 91) )
{
throw gcnew ArgumentException( "value must be >= 0 and <= 91","n" );
}
long result = 0;
// Abort the operation if the user has cancelled.
// Note that a call to CancelAsync may have set 
// CancellationPending to true just after the
// last invocation of this method exits, so this 
// code will not have the opportunity to set the 
// DoWorkEventArgs.Cancel flag to true. This means
// that RunWorkerCompletedEventArgs.Cancelled will
// not be set to true in your RunWorkerCompleted
// event handler. This is a race condition.
if ( worker->CancellationPending )
{
e->Cancel = true;
}
else
{
if ( n < 2 )
{
result = 1;
}
else
{
result = ComputeFibonacci( n - 1, worker, e ) + ComputeFibonacci( n - 2, worker, e );
}
// Report progress as a percentage of the total task.
int percentComplete = (int)((float)n / (float)numberToCompute * 100);
if ( percentComplete > highestPercentageReached )
{
highestPercentageReached = percentComplete;
worker->ReportProgress( percentComplete );
}
}
return result;
}
void InitializeComponent()
{
this->numericUpDown1 = gcnew System::Windows::Forms::NumericUpDown;
this->startAsyncButton = gcnew System::Windows::Forms::Button;
this->cancelAsyncButton = gcnew System::Windows::Forms::Button;
this->resultLabel = gcnew System::Windows::Forms::Label;
this->progressBar1 = gcnew System::Windows::Forms::ProgressBar;
this->backgroundWorker1 = gcnew System::ComponentModel::BackgroundWorker;
(dynamic_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown1))->BeginInit();
this->SuspendLayout();
// 
// numericUpDown1
// 
this->numericUpDown1->Location = System::Drawing::Point( 16, 16 );
array<Int32>^temp0 = {91,0,0,0};
this->numericUpDown1->Maximum = System::Decimal( temp0 );
array<Int32>^temp1 = {1,0,0,0};
this->numericUpDown1->Minimum = System::Decimal( temp1 );
this->numericUpDown1->Name = "numericUpDown1";
this->numericUpDown1->Size = System::Drawing::Size( 80, 20 );
this->numericUpDown1->TabIndex = 0;
array<Int32>^temp2 = {1,0,0,0};
this->numericUpDown1->Value = System::Decimal( temp2 );
// 
// startAsyncButton
// 
this->startAsyncButton->Location = System::Drawing::Point( 16, 72 );
this->startAsyncButton->Name = "startAsyncButton";
this->startAsyncButton->Size = System::Drawing::Size( 120, 23 );
this->startAsyncButton->TabIndex = 1;
this->startAsyncButton->Text = "Start Async";
this->startAsyncButton->Click += gcnew System::EventHandler( this, &FibonacciForm::startAsyncButton_Click );
// 
// cancelAsyncButton
// 
this->cancelAsyncButton->Enabled = false;
this->cancelAsyncButton->Location = System::Drawing::Point( 153, 72 );
this->cancelAsyncButton->Name = "cancelAsyncButton";
this->cancelAsyncButton->Size = System::Drawing::Size( 119, 23 );
this->cancelAsyncButton->TabIndex = 2;
this->cancelAsyncButton->Text = "Cancel Async";
this->cancelAsyncButton->Click += gcnew System::EventHandler( this, &FibonacciForm::cancelAsyncButton_Click );
// 
// resultLabel
// 
this->resultLabel->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
this->resultLabel->Location = System::Drawing::Point( 112, 16 );
this->resultLabel->Name = "resultLabel";
this->resultLabel->Size = System::Drawing::Size( 160, 23 );
this->resultLabel->TabIndex = 3;
this->resultLabel->Text = "(no result)";
this->resultLabel->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;
// 
// progressBar1
// 
this->progressBar1->Location = System::Drawing::Point( 18, 48 );
this->progressBar1->Name = "progressBar1";
this->progressBar1->Size = System::Drawing::Size( 256, 8 );
this->progressBar1->Step = 2;
this->progressBar1->TabIndex = 4;
// 
// backgroundWorker1
// 
this->backgroundWorker1->WorkerReportsProgress = true;
this->backgroundWorker1->WorkerSupportsCancellation = true;
// 
// FibonacciForm
// 
this->ClientSize = System::Drawing::Size( 292, 118 );
this->Controls->Add( this->progressBar1 );
this->Controls->Add( this->resultLabel );
this->Controls->Add( this->cancelAsyncButton );
this->Controls->Add( this->startAsyncButton );
this->Controls->Add( this->numericUpDown1 );
this->Name = "FibonacciForm";
this->Text = "Fibonacci Calculator";
(dynamic_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown1))->EndInit();
this->ResumeLayout( false );
}
};
[STAThread]
int main()
{
Application::Run( gcnew FibonacciForm );
}
c#描述
namespace BwTester
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
BackgroundWorker backgroundWorker;
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
backgroundWorker.RunWorkerAsync();
}
void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 500; i++)
{
backgroundWorker.ReportProgress(i);
Thread.Sleep(100);
}
}
}
}