词条 | 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条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。