请输入您要查询的百科知识:

 

词条 BackgroundWorker
释义

BackgroundWorker是.net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 始终处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。

该控件有三个事件:

DoWork 、ProgressChanged 和 RunWorkerCompleted

在程序中调用RunWorkerAsync方法则会启动DoWork事件的事件处理,当在事件处理过程中,调用 ReportProgress方法则会启动ProgressChanged事件的事件处理,而当DoWork事件处理完成时,则会触发RunWorkerCompleted事件。

您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged和 RunWorkerCompleted 事件与用户界面进行通信。

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);

}

}

}

}

随便看

 

百科全书收录4421916条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。

 

Copyright © 2004-2023 Cnenc.net All Rights Reserved
更新时间:2025/2/27 9:22:44