BackgroundWorker 组件概述
许多经常执行的操作可能需要很长的执行时间。例如:
*
图像下载
*
Web 服务调用
*
文件下载和上载(包括点对点应用程序)
*
复杂的本地计算
*
数据库事务
*
本地磁盘访问(相对于内存访问来说其速度很慢)
例子里是微软本身的例子和我的例子,一个窗体两个 BackgroundWorker,两个可以一起运行啊
第一个是求斐波纳契数
http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker%28VS.80%29.aspx
第二个是不断地向richtextbox里添加行,类似于日志,完成一个后在里面显示一下。
微软的东西都封装了哎。例子外有几个问题:
(1)“您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。”
但是测试发现,放在ProgressChangedUI还是没有响应的。所以只能放在 DoWork里
(2) 如果出现Cross-thread operation not valid: Control 'RichTextBox1' accessed from a thread other than the thread it was created on.
在窗体的构造方法里加上这个即可。
Control.CheckForIllegalCrossThreadCalls = False
.vb
Imports System.ComponentModel


Public Class TestBackGroundWorkClass TestBackGroundWork
Private lStrValue = String.Empty
Private numberToCompute As Integer = 0
Private highestPercentageReached As Integer = 0

Sub New()Sub New()

' This call is required by the Windows Form Designer.
InitializeComponent()
Me.BackgroundWorker1.WorkerSupportsCancellation = True
' Add any initialization after the InitializeComponent() call.
'Control.CheckForIllegalCrossThreadCalls = False
End Sub


msdn 例子#Region "msdn 例子"

Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'befor backgroundwork
' Me.TextBox2.Text = mFnGetNum(CInt(TextBox1.Text))
TextBox2.Text = String.Empty
numberToCompute = CInt(TextBox1.Text)
highestPercentageReached = 0
BackgroundWorker1.RunWorkerAsync(numberToCompute)
Me.Button1.Enabled = False
While Me.BackgroundWorker1.IsBusy
' Keep UI messages moving, so the form remains
' responsive during the asynchronous operation.
Application.DoEvents()
End While
Me.Button1.Enabled = True
End Sub


Private Sub Button2_Click()Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.BackgroundWorker1.CancelAsync()
End Sub



Public Function mFnGetNum()Function mFnGetNum(ByVal Num As Integer, _
ByVal worker As BackgroundWorker, _
ByVal e As DoWorkEventArgs) As Long
Dim result As Long = 0

If worker.CancellationPending Then
e.Cancel = True
Else
If Num < 2 Then
result = 1
Else
result = mFnGetNum(Num - 1, worker, e) + _
mFnGetNum(Num - 2, worker, e)
End If
' Report progress as a percentage of the total task.
Dim percentComplete As Integer = _
CSng(Num) / CSng(numberToCompute) * 100
If percentComplete > highestPercentageReached Then
highestPercentageReached = percentComplete
worker.ReportProgress(percentComplete)
End If
End If
Return result
End Function



Public Function mFnGetNum()Function mFnGetNum(ByVal Num As Integer) As Long

Dim result As Long = 0
If Num < 2 Then
result = 1
Else
result = mFnGetNum(Num - 1) + mFnGetNum(Num - 2)
End If
Return result

End Function



Private Sub BackgroundWorker1_DoWork()Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim worker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker)

e.Result = mFnGetNum(e.Argument, worker, e)
End Sub


Private Sub BackgroundWorker1_ProgressChanged()Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage

End Sub


Private Sub BackgroundWorker1_RunWorkerCompleted()Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If Not (e.Error Is 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.
TextBox2.Text = "Canceled"
Else
' Finally, handle the case where the operation succeeded.
TextBox2.Text = e.Result.ToString()
End If
End Sub


#End Region



不停的向RichTextBox添加行#Region "不停的向RichTextBox添加行"


Private Sub Button3_Click()Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Me.RichTextBox1.Text = String.Empty
BackgroundWorker2.RunWorkerAsync()
Me.Button3.Enabled = False
While Me.BackgroundWorker2.IsBusy
' Keep UI messages moving, so the form remains
' responsive during the asynchronous operation.
Application.DoEvents()
End While
Me.Button3.Enabled = True

'Me.RichTextBox1.LoadFile("C:\Project\AppTest1\AppTest1\privacysummary.rtf")
End Sub


Private Sub BackgroundWorker2_DoWork()Sub BackgroundWorker2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
'Dim txt As RichTextBox = CType(e.Argument, RichTextBox)
For i As Integer = 0 To 5000
'lStrValue = "Text" + i.ToString() + "\r\n"
'BackgroundWorker2.ReportProgress(2)
Me.RichTextBox1.AppendText("Text" + i.ToString() + vbCrLf)
Next

End Sub


Private Sub BackgroundWorker2_ProgressChanged()Sub BackgroundWorker2_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker2.ProgressChanged
'您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
' 但是测试发现,放在这里UI还是没有响应的。所以只能放在 DoWork里
' Me.RichTextBox1.Text += lStrValue
End Sub
#End Region

End Class
.vb design
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

Partial Class TestBackGroundWorkClass TestBackGroundWork
Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _

Protected Overrides Sub Dispose()Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _

Private Sub InitializeComponent()Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.TextBox2 = New System.Windows.Forms.TextBox
Me.BackgroundWorker1 = New System.ComponentModel.BackgroundWorker
Me.ProgressBar1 = New System.Windows.Forms.ProgressBar
Me.Button3 = New System.Windows.Forms.Button
Me.RichTextBox1 = New System.Windows.Forms.RichTextBox
Me.BackgroundWorker2 = New System.ComponentModel.BackgroundWorker
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(48, 130)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(75, 23)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Start"
Me.Button1.UseVisualStyleBackColor = True
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(166, 130)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(75, 23)
Me.Button2.TabIndex = 1
Me.Button2.Text = "Cancel"
Me.Button2.UseVisualStyleBackColor = True
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(32, 23)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(130, 20)
Me.TextBox1.TabIndex = 2
'
'TextBox2
'
Me.TextBox2.Location = New System.Drawing.Point(204, 23)
Me.TextBox2.Name = "TextBox2"
Me.TextBox2.Size = New System.Drawing.Size(241, 20)
Me.TextBox2.TabIndex = 2
'
'BackgroundWorker1
'
Me.BackgroundWorker1.WorkerReportsProgress = True
Me.BackgroundWorker1.WorkerSupportsCancellation = True
'
'ProgressBar1
'
Me.ProgressBar1.Location = New System.Drawing.Point(32, 80)
Me.ProgressBar1.Name = "ProgressBar1"
Me.ProgressBar1.Size = New System.Drawing.Size(413, 23)
Me.ProgressBar1.TabIndex = 3
'
'Button3
'
Me.Button3.Location = New System.Drawing.Point(277, 130)
Me.Button3.Name = "Button3"
Me.Button3.Size = New System.Drawing.Size(75, 23)
Me.Button3.TabIndex = 4
Me.Button3.Text = "AppandText"
Me.Button3.UseVisualStyleBackColor = True
'
'RichTextBox1
'
Me.RichTextBox1.AutoWordSelection = True
Me.RichTextBox1.Location = New System.Drawing.Point(48, 159)
Me.RichTextBox1.Name = "RichTextBox1"
Me.RichTextBox1.Size = New System.Drawing.Size(819, 262)
Me.RichTextBox1.TabIndex = 5
Me.RichTextBox1.Text = ""
'
'BackgroundWorker2
'
Me.BackgroundWorker2.WorkerReportsProgress = True
Me.BackgroundWorker2.WorkerSupportsCancellation = True
'
'TestBackGroundWork
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(949, 446)
Me.Controls.Add(Me.RichTextBox1)
Me.Controls.Add(Me.Button3)
Me.Controls.Add(Me.ProgressBar1)
Me.Controls.Add(Me.TextBox2)
Me.Controls.Add(Me.TextBox1)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Name = "TestBackGroundWork"
Me.Text = "TestBackGroundWork"
Me.ResumeLayout(False)
Me.PerformLayout()

End Sub
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
Friend WithEvents ProgressBar1 As System.Windows.Forms.ProgressBar
Private WithEvents BackgroundWorker1 As System.ComponentModel.BackgroundWorker
Friend WithEvents Button3 As System.Windows.Forms.Button
Friend WithEvents RichTextBox1 As System.Windows.Forms.RichTextBox
Friend WithEvents BackgroundWorker2 As System.ComponentModel.BackgroundWorker
End Class
