BackgroundWorker 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
对单独的线程执行操作。
public ref class BackgroundWorker : IDisposable
public ref class BackgroundWorker : System::ComponentModel::Component
public class BackgroundWorker : IDisposable
public class BackgroundWorker : System.ComponentModel.Component
type BackgroundWorker = class
interface IDisposable
type BackgroundWorker = class
inherit Component
Public Class BackgroundWorker
Implements IDisposable
Public Class BackgroundWorker
Inherits Component
- 继承
-
BackgroundWorker
- 继承
- 实现
示例
下面的代码示例演示了异步执行耗时操作的类的 BackgroundWorker 基础知识。 下图显示了输出示例。
若要尝试此代码,请创建 Windows 窗体应用程序。 添加名为和resultLabel添加两Button个Label命名startAsyncButton控件和cancelAsyncButton的控件。 为这两个按钮创建 Click 事件处理程序。 在工具箱的“
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace BackgroundWorkerSimple;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
void startAsyncButton_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)
{
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();
}
}
void cancelAsyncButton_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation)
{
// Cancel the asynchronous operation.
backgroundWorker1.CancelAsync();
}
}
// This event handler is where the time-consuming work is done.
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress(i * 10);
}
}
}
// This event handler updates the progress.
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) =>
resultLabel.Text = e.ProgressPercentage.ToString() + "%";
// This event handler deals with the results of the background operation.
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) =>
resultLabel.Text = e.Cancelled ?
"Canceled!"
: e.Error != null ? "Error: " + e.Error.Message : "Done!";
}
Imports System.ComponentModel
Public Class Form1
Public Sub New()
InitializeComponent()
backgroundWorker1.WorkerReportsProgress = True
backgroundWorker1.WorkerSupportsCancellation = True
End Sub
Private Sub startAsyncButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles startAsyncButton.Click
If Not backgroundWorker1.IsBusy Then
' Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync()
End If
End Sub
Private Sub cancelAsyncButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cancelAsyncButton.Click
If backgroundWorker1.WorkerSupportsCancellation Then
' Cancel the asynchronous operation.
backgroundWorker1.CancelAsync()
End If
End Sub
' This event handler is where the time-consuming work is done.
Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, _
ByVal e As DoWorkEventArgs) Handles backgroundWorker1.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
Dim i As Integer
For i = 1 To 10
If (worker.CancellationPending) Then
e.Cancel = True
Exit For
Else
' Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500)
worker.ReportProgress(i * 10)
End If
Next
End Sub
' This event handler updates the progress.
Private Sub backgroundWorker1_ProgressChanged(ByVal sender As System.Object, _
ByVal e As ProgressChangedEventArgs) Handles backgroundWorker1.ProgressChanged
resultLabel.Text = (e.ProgressPercentage.ToString() + "%")
End Sub
' This event handler deals with the results of the background operation.
Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, _
ByVal e As RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
If e.Cancelled Then
resultLabel.Text = "Canceled!"
ElseIf e.Error IsNot Nothing Then
resultLabel.Text = "Error: " & e.Error.Message
Else
resultLabel.Text = "Done!"
End If
End Sub
End Class
下面的代码示例演示如何 BackgroundWorker 使用类异步执行耗时的操作。 下图显示了输出示例。
该操作计算所选的 Fibonacci 数,在计算继续时报告进度更新,并允许取消挂起的计算。
#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 );
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace BackgroundWorkerExample;
public class FibonacciForm : Form
{
int numberToCompute;
int highestPercentageReached;
NumericUpDown numericUpDown1;
Button startAsyncButton;
Button cancelAsyncButton;
ProgressBar progressBar1;
Label resultLabel;
BackgroundWorker backgroundWorker1;
public FibonacciForm()
{
InitializeComponent();
InitializeBackgroundWorker();
}
// Set up the BackgroundWorker object by
// attaching event handlers.
void InitializeBackgroundWorker()
{
backgroundWorker1.DoWork +=
backgroundWorker1_DoWork;
backgroundWorker1.RunWorkerCompleted +=
backgroundWorker1_RunWorkerCompleted;
backgroundWorker1.ProgressChanged +=
backgroundWorker1_ProgressChanged;
}
void startAsyncButton_Click(object sender,
EventArgs e)
{
// Reset the text in the result label.
resultLabel.Text = string.Empty;
// Disable the UpDown control until
// the asynchronous operation is done.
numericUpDown1.Enabled = false;
// Disable the Start button until
// the asynchronous operation is done.
startAsyncButton.Enabled = false;
// Enable the Cancel button while
// the asynchronous operation runs.
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(object sender,
EventArgs e)
{
// Cancel the asynchronous operation.
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 = sender as BackgroundWorker;
// 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((int)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 != null)
{
_ = MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// 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 = "Canceled";
}
else
{
// Finally, handle the case where the operation
// succeeded.
resultLabel.Text = e.Result.ToString();
}
// Enable the UpDown control.
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) => 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 is < 0 or > 91)
{
throw new ArgumentException(
"value must be >= 0 and <= 91", nameof(n));
}
long result = 0;
// Abort the operation if the user has canceled.
// 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
{
result = n < 2
? 1
: ComputeFibonacci(n - 1, worker, e) +
ComputeFibonacci(n - 2, worker, e);
// Report progress as a percentage of the total task.
int percentComplete =
(int)(n / (float)numberToCompute * 100);
if (percentComplete > highestPercentageReached)
{
highestPercentageReached = percentComplete;
worker.ReportProgress(percentComplete);
}
}
return result;
}
#region Windows Form Designer generated code
void InitializeComponent()
{
numericUpDown1 = new NumericUpDown();
startAsyncButton = new Button();
cancelAsyncButton = new Button();
resultLabel = new Label();
progressBar1 = new ProgressBar();
backgroundWorker1 = new BackgroundWorker();
((ISupportInitialize)numericUpDown1).BeginInit();
SuspendLayout();
//
// numericUpDown1
//
numericUpDown1.Location = new Point(16, 16);
numericUpDown1.Maximum = new decimal(new int[] {
91,
0,
0,
0});
numericUpDown1.Minimum = new decimal(new int[] {
1,
0,
0,
0});
numericUpDown1.Name = "numericUpDown1";
numericUpDown1.Size = new Size(80, 20);
numericUpDown1.TabIndex = 0;
numericUpDown1.Value = new decimal(new int[] {
1,
0,
0,
0});
//
// startAsyncButton
//
startAsyncButton.Location = new Point(16, 72);
startAsyncButton.Name = "startAsyncButton";
startAsyncButton.Size = new Size(120, 23);
startAsyncButton.TabIndex = 1;
startAsyncButton.Text = "Start Async";
startAsyncButton.Click += startAsyncButton_Click;
//
// cancelAsyncButton
//
cancelAsyncButton.Enabled = false;
cancelAsyncButton.Location = new Point(153, 72);
cancelAsyncButton.Name = "cancelAsyncButton";
cancelAsyncButton.Size = new Size(119, 23);
cancelAsyncButton.TabIndex = 2;
cancelAsyncButton.Text = "Cancel Async";
cancelAsyncButton.Click += cancelAsyncButton_Click;
//
// resultLabel
//
resultLabel.BorderStyle = BorderStyle.Fixed3D;
resultLabel.Location = new Point(112, 16);
resultLabel.Name = "resultLabel";
resultLabel.Size = new Size(160, 23);
resultLabel.TabIndex = 3;
resultLabel.Text = "(no result)";
resultLabel.TextAlign = ContentAlignment.MiddleCenter;
//
// progressBar1
//
progressBar1.Location = new Point(18, 48);
progressBar1.Name = "progressBar1";
progressBar1.Size = new Size(256, 8);
progressBar1.Step = 2;
progressBar1.TabIndex = 4;
//
// backgroundWorker1
//
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
//
// FibonacciForm
//
ClientSize = new Size(1794, 927);
Controls.Add(progressBar1);
Controls.Add(resultLabel);
Controls.Add(cancelAsyncButton);
Controls.Add(startAsyncButton);
Controls.Add(numericUpDown1);
Name = "FibonacciForm";
Text = "Fibonacci Calculator";
((ISupportInitialize)numericUpDown1).EndInit();
ResumeLayout(false);
}
#endregion
[STAThread]
static void Main() => Application.Run(new FibonacciForm());
}
Imports System.ComponentModel
Imports System.Windows.Forms
Public Class FibonacciForm
Inherits Form
Private numberToCompute As Integer = 0
Private highestPercentageReached As Integer = 0
Private numericUpDown1 As NumericUpDown
Private WithEvents startAsyncButton As Button
Private WithEvents cancelAsyncButton As Button
Private progressBar1 As ProgressBar
Private resultLabel As Label
Private WithEvents backgroundWorker1 As System.ComponentModel.BackgroundWorker
Public Sub New()
InitializeComponent()
End Sub
Private Sub startAsyncButton_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) _
Handles startAsyncButton.Click
' Reset the text in the result label.
resultLabel.Text = [String].Empty
' Disable the UpDown control until
' the asynchronous operation is done.
numericUpDown1.Enabled = False
' Disable the Start button until
' the asynchronous operation is done.
startAsyncButton.Enabled = False
' Enable the Cancel button while
' the asynchronous operation runs.
cancelAsyncButton.Enabled = True
' Get the value from the UpDown control.
numberToCompute = CInt(numericUpDown1.Value)
' Reset the variable for percentage tracking.
highestPercentageReached = 0
' Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync(numberToCompute)
End Sub
Private Sub cancelAsyncButton_Click(
ByVal sender As System.Object,
ByVal e As System.EventArgs) _
Handles cancelAsyncButton.Click
' Cancel the asynchronous operation.
backgroundWorker1.CancelAsync()
' Disable the Cancel button.
cancelAsyncButton.Enabled = False
End Sub
' This event handler is where the actual work is done.
Private Sub backgroundWorker1_DoWork(
ByVal sender As Object,
ByVal e As DoWorkEventArgs) _
Handles backgroundWorker1.DoWork
' Get the BackgroundWorker object that raised this event.
Dim worker As BackgroundWorker =
CType(sender, BackgroundWorker)
' 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(e.Argument, worker, e)
End Sub
' This event handler deals with the results of the
' background operation.
Private Sub backgroundWorker1_RunWorkerCompleted(
ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
Handles backgroundWorker1.RunWorkerCompleted
' First, handle the case where an exception was thrown.
If (e.Error IsNot Nothing) Then
MessageBox.Show(e.Error.Message)
ElseIf e.Cancelled Then
' Next, handle the case where the user canceled 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 = "Canceled"
Else
' Finally, handle the case where the operation succeeded.
resultLabel.Text = e.Result.ToString()
End If
' Enable the UpDown control.
numericUpDown1.Enabled = True
' Enable the Start button.
startAsyncButton.Enabled = True
' Disable the Cancel button.
cancelAsyncButton.Enabled = False
End Sub
' This event handler updates the progress bar.
Private Sub backgroundWorker1_ProgressChanged(
ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
Handles backgroundWorker1.ProgressChanged
progressBar1.Value = e.ProgressPercentage
End Sub
' 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.
Function ComputeFibonacci(
ByVal n As Integer,
ByVal worker As BackgroundWorker,
ByVal e As DoWorkEventArgs) As Long
' The parameter n must be >= 0 and <= 91.
' Fib(n), with n > 91, overflows a long.
If n < 0 OrElse n > 91 Then
Throw New ArgumentException(
"value must be >= 0 and <= 91", "n")
End If
Dim result As Long = 0
' Abort the operation if the user has canceled.
' 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 Then
e.Cancel = True
Else
If n < 2 Then
result = 1
Else
result = ComputeFibonacci(n - 1, worker, e) +
ComputeFibonacci(n - 2, worker, e)
End If
' Report progress as a percentage of the total task.
Dim percentComplete As Integer =
CSng(n) / CSng(numberToCompute) * 100
If percentComplete > highestPercentageReached Then
highestPercentageReached = percentComplete
worker.ReportProgress(percentComplete)
End If
End If
Return result
End Function
Private Sub InitializeComponent()
numericUpDown1 = New NumericUpDown
startAsyncButton = New Button
cancelAsyncButton = New Button
resultLabel = New Label
progressBar1 = New ProgressBar
backgroundWorker1 = New System.ComponentModel.BackgroundWorker
CType(numericUpDown1, System.ComponentModel.ISupportInitialize).BeginInit()
SuspendLayout()
'
'numericUpDown1
'
numericUpDown1.Location = New System.Drawing.Point(16, 16)
numericUpDown1.Maximum = New Decimal(New Integer() {91, 0, 0, 0})
numericUpDown1.Minimum = New Decimal(New Integer() {1, 0, 0, 0})
numericUpDown1.Name = "numericUpDown1"
numericUpDown1.Size = New System.Drawing.Size(80, 20)
numericUpDown1.TabIndex = 0
numericUpDown1.Value = New Decimal(New Integer() {1, 0, 0, 0})
'
'startAsyncButton
'
startAsyncButton.Location = New System.Drawing.Point(16, 72)
startAsyncButton.Name = "startAsyncButton"
startAsyncButton.Size = New System.Drawing.Size(120, 23)
startAsyncButton.TabIndex = 1
startAsyncButton.Text = "Start Async"
'
'cancelAsyncButton
'
cancelAsyncButton.Enabled = False
cancelAsyncButton.Location = New System.Drawing.Point(153, 72)
cancelAsyncButton.Name = "cancelAsyncButton"
cancelAsyncButton.Size = New System.Drawing.Size(119, 23)
cancelAsyncButton.TabIndex = 2
cancelAsyncButton.Text = "Cancel Async"
'
'resultLabel
'
resultLabel.BorderStyle = BorderStyle.Fixed3D
resultLabel.Location = New System.Drawing.Point(112, 16)
resultLabel.Name = "resultLabel"
resultLabel.Size = New System.Drawing.Size(160, 23)
resultLabel.TabIndex = 3
resultLabel.Text = "(no result)"
resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'progressBar1
'
progressBar1.Location = New System.Drawing.Point(18, 48)
progressBar1.Name = "progressBar1"
progressBar1.Size = New System.Drawing.Size(256, 8)
progressBar1.TabIndex = 4
'
'backgroundWorker1
'
backgroundWorker1.WorkerReportsProgress = True
backgroundWorker1.WorkerSupportsCancellation = True
'
'FibonacciForm
'
ClientSize = New System.Drawing.Size(292, 118)
Controls.Add(progressBar1)
Controls.Add(resultLabel)
Controls.Add(cancelAsyncButton)
Controls.Add(startAsyncButton)
Controls.Add(numericUpDown1)
Name = "FibonacciForm"
Text = "Fibonacci Calculator"
CType(numericUpDown1, System.ComponentModel.ISupportInitialize).EndInit()
ResumeLayout(False)
End Sub
<STAThread()> _
Shared Sub Main()
Application.Run(New FibonacciForm)
End Sub
End Class
注解
该 BackgroundWorker 类允许你在单独的专用线程上运行操作。 下载和数据库事务等耗时的操作可能会导致用户界面(UI)在运行时停止响应。 如果想要响应式 UI,并且遇到与此类操作相关的长时间延迟,该 BackgroundWorker 类将提供一个方便的解决方案。
若要在后台执行耗时的操作,请创建 BackgroundWorker 并侦听报告操作进度的事件,并在操作完成后发出信号。 可以通过编程方式创建BackgroundWorker,也可以从工具箱的“组件”选项卡将其拖到窗体上。 如果在 Windows 窗体设计器中创建 BackgroundWorker ,它将显示在组件托盘中,其属性将显示在“属性”窗口中。
若要为后台操作设置,请为 DoWork 事件添加事件处理程序。 在此事件处理程序中调用耗时的操作。 若要启动操作,请调用 RunWorkerAsync。 若要接收进度更新通知,请处理事件 ProgressChanged 。 若要在操作完成后接收通知,请处理该 RunWorkerCompleted 事件。
注释
必须小心不要操作事件处理程序中的任何 DoWork 用户界面对象。 而是通过 ProgressChanged 事件 RunWorkerCompleted 与用户界面进行通信。
BackgroundWorker 事件不会跨 AppDomain 边界封送。 不要使用 BackgroundWorker 组件在多个 AppDomain线程中执行多线程操作。
如果后台操作需要参数,请使用参数调用 RunWorkerAsync 。 在事件处理程序中 DoWork ,可以从属性中提取参数 DoWorkEventArgs.Argument 。
有关BackgroundWorker的详细信息,请参阅如何:在后台运行操作。
构造函数
| 名称 | 说明 |
|---|---|
| BackgroundWorker() |
初始化 BackgroundWorker 类的新实例。 |
属性
| 名称 | 说明 |
|---|---|
| CancellationPending |
获取一个值,该值指示应用程序是否请求取消后台操作。 |
| CanRaiseEvents |
获取一个值,该值指示组件是否可以引发事件。 (继承自 Component) |
| Container |
IContainer获取包含 .Component (继承自 Component) |
| DesignMode |
获取一个值,该值指示当前是否 Component 处于设计模式。 (继承自 Component) |
| Events |
获取附加到此 Component对象的事件处理程序的列表。 (继承自 Component) |
| IsBusy |
获取一个值,该值指示是否 BackgroundWorker 正在运行异步操作。 |
| Site | (继承自 Component) |
| WorkerReportsProgress |
获取或设置一个值,该值指示是否可以 BackgroundWorker 报告进度更新。 |
| WorkerSupportsCancellation |
获取或设置一个值,该值指示是否 BackgroundWorker 支持异步取消。 |
方法
活动
| 名称 | 说明 |
|---|---|
| Disposed |
当组件通过对方法的调用 Dispose() 释放时发生。 (继承自 Component) |
| DoWork |
调用时 RunWorkerAsync() 发生。 |
| ProgressChanged |
调用时 ReportProgress(Int32) 发生。 |
| RunWorkerCompleted |
当后台操作完成、已取消或引发异常时发生。 |