我使用VB.NET 2005编程。我使用BackgroundWorker
加载大型列表或文本文件并进行处理。
是否可以使用相同的后台工作程序来处理其他内容,即处理已加载的文本文件? 像
这样的东西Dim bwkMain as New BackgroundWorker()
如果可能的话,我该如何以与第一个相同的形式实现它呢?
修改
问题是:在完成一项任务后,是否可以将相同的BackgroundWorker用于另一项任务?
答案 0 :(得分:7)
可以让单个BackgroundWorker执行两个或更多不同的操作。需要注意的是,如果您尝试让BackgroundWorker一次执行多项操作,则会导致代码失败。
以下是如何让BackgroundWorker进行多项活动的简要概述。
DoWork
事件中采用不同的编码样式。)RunWorkerAsync
方法,该参数指定要执行的操作。 DoWork
事件处理程序中,检查传递的参数(e.Argument
)并执行所需的活动。以下是一些示例代码,可指导您完成:
Public Class Form1
Public WithEvents bgwWorker1 As System.ComponentModel.BackgroundWorker
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
bgwWorker1 = New System.ComponentModel.BackgroundWorker
With bgwWorker1
.WorkerReportsProgress = True 'we'll need to report progress
.WorkerSupportsCancellation = True 'allows the user to stop the activity
End With
End Sub
Private Sub Form1_Disposed() Handles Me.Disposed
'you'll need to dispose the backgroundworker when the form closes.
bgwWorker1.Dispose()
End Sub
Private Sub btnStart_Click() Handles btnStart.Click
'check if the backgroundworker is doing something
Dim waitCount = 0
'wait 5 seconds for the background worker to be free
Do While bgwWorker1.IsBusy AndAlso waitCount <= 5
bgwWorker1.CancelAsync() 'tell the backgroundworker to stop
Threading.Thread.Sleep(1000) 'wait for 1 second
waitCount += 1
Loop
'ensure the worker has stopped else the code will fail
If bgwWorker1.IsBusy Then
MsgBox("The background worker could not be cancelled.")
Else
If optStep2.Checked Then
bgwWorker1.RunWorkerAsync(2)
ElseIf optStep3.Checked Then
bgwWorker1.RunWorkerAsync(3)
End If
btnStart.Enabled = False
btnStop.Enabled = True
End If
End Sub
Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
'to stop the worker, send the cancel message
bgwWorker1.CancelAsync()
End Sub
Private Sub bgwWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwWorker1.DoWork
'get the value to be used in performing the steps
'in your case, you might have to convert it to a string or something
'and then do a Select Case on the result.
Dim stepValue = CInt(e.Argument)
'you cannot change the property of any control from a thread different
'from the one that created it (the UI Thread) so this code would fail.
'txtResults.Text &= "Starting count in steps of " & stepValue & vbCrLf
'to perform a thread-safe activity, use the ReportProgress method like so
bgwWorker1.ReportProgress(0, "Reported: Starting count in steps of " & stepValue & vbCrLf)
'or invoke it through an anonymous or named method
Me.Invoke(Sub() txtResults.Text &= "Invoked (anon): Starting count in steps of " & stepValue & vbCrLf)
SetTextSafely("Invoked (named): Starting count in steps of " & stepValue & vbCrLf)
For i = 0 To 1000 Step stepValue
'Visual Studio Warns: Using the iteration variable in a lambda expression may have unexpected results.
' Instead, create a local variable within the loop and assign it the value of
' the iteration variable.
Dim safeValue = i.ToString
Me.Invoke(Sub() txtResults.Text &= safeValue & vbCrLf)
'delibrately slow the thread
Threading.Thread.Sleep(300)
'check if there is a canellation pending
If bgwWorker1.CancellationPending Then
e.Cancel = True 'set this to true so we will know the activities were cancelled
Exit Sub
End If
Next
End Sub
Private Sub SetTextSafely(ByVal text As String)
If Me.InvokeRequired Then
Me.Invoke(Sub() SetTextSafely(text))
Else
txtResults.Text &= text
End If
End Sub
Private Sub bgwWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwWorker1.ProgressChanged
'everything done in this event handler is on the UI thread so it is thread safe
txtResults.Text &= e.UserState.ToString
End Sub
Private Sub bgwWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwWorker1.RunWorkerCompleted
'everything done in this event handler is on the UI thread so it is thread safe
If Not e.Cancelled Then
txtResults.Text &= "Activities have been completed."
Else
txtResults.Text &= "Activities were cancelled."
End If
btnStart.Enabled = True
btnStop.Enabled = False
End Sub
Private Sub txtResults_TextChanged() Handles txtResults.TextChanged
'place the caret at the end of the line and then scroll to it
'so that we always see what is happening.
txtResults.SelectionStart = txtResults.TextLength
txtResults.ScrollToCaret()
End Sub
End Class
这是随之而来的形式:
另请考虑阅读MSDN上的以下文章:
上面的代码仅适用于VB 10(VS 2010)。为了在其他版本的VB中实现相同的代码,您必须编写大量代码,因为它们不支持匿名代理。
在旧版本的VB中,行
Public Sub Sample()
Me.Invoke(Sub() txtResults.Text &= safeValue & vbCrLf)
End Sub
翻译成这样的东西:
Public Delegate AnonymousMethodDelegate(value as String)
Public Sub AnonymousMethod(value as String)
txtResults.Text &= value
End Sub
Public Sub Sample()
Me.Invoke(New AnonymousMethodDelegate(AddressOf AnonymousMethod), safeValue & vbCrLf)
End Sub
按照以下步骤使代码在VB 10之前工作
添加此代理
Delegate Sub SetTextSafelyDelegate(ByVal text As String)
然后将所有Me.Invoke(Sub() SetTextSafely(text))
更改为
Me.Invoke(New SetTextSafelyDelegate(AddressOf SetTextSafely), text)
另请注意,在我使用匿名委托设置文本的任何地方,您都必须重写代码以调用SetTextSafely
方法。
例如,Me.Invoke(Sub() txtResults.Text &= safeValue & vbCrLf)
的for循环部分中的行bgwWorker_DoWork
将变为SetTextSafely(safeValue & vbCrLf)
如果您想了解有关代表的更多信息,请阅读以下文章(均来自MSDN)
答案 1 :(得分:2)
由于你不能并行运行你的两个任务,你可以在同一个背景工作者中按顺序执行它们
BackgroundWorker1.RunWorkerAsync(args)
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
DoTask1() ' Read files.
DoTask2() ' Process data that was read.
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles BackgroundWorker1.RunWorkerCompleted
'Tasks Done
End Sub
答案 2 :(得分:1)
非常含糊。启动另一个后台工作程序并让第一个后台工作程序等待它完成是没有意义的。如果您可以同时执行某些操作,则只能从多个线程中获益。读取文件然后处理它是一个不能重叠的顺序操作。也许你可以同时进行一些处理,但这是你的问题无法解决的问题。