.net 如何使用一个后台工作人员进行不同的活动?
我正在使用VB.NET2005编程。我正在使用BackgroundWorker加载一个大列表或文本文件并对其进行处理 是否可以使用相同的后台工作程序处理其他内容,即处理加载的文本文件? 糟糕的.net 如何使用一个后台工作人员进行不同的活动?,.net,vb.net,backgroundworker,.net,Vb.net,Backgroundworker,我正在使用VB.NET2005编程。我正在使用BackgroundWorker加载一个大列表或文本文件并对其进行处理 是否可以使用相同的后台工作程序处理其他内容,即处理加载的文本文件? 糟糕的 Dim bwkMain as New BackgroundWorker() 如果可能的话,我如何以与第一个版本相同的形式实现它 编辑 问题是:在完成一项任务后,是否可以将同一个BackgroundWorker用于另一项任务?由于无法并行运行两项任务,因此可以在同一个BackgroundWorker中按如
Dim bwkMain as New BackgroundWorker()
如果可能的话,我如何以与第一个版本相同的形式实现它
编辑
问题是:在完成一项任务后,是否可以将同一个BackgroundWorker用于另一项任务?由于无法并行运行两项任务,因此可以在同一个BackgroundWorker中按如下顺序执行它们
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
因为您不能并行运行两个任务,所以您可以在相同的backgroundworker中按顺序执行它们,如下所示
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
非常模糊。启动另一个后台工作程序并让第一个后台工作程序等待它完成是没有意义的。如果你能同时做一些事情,你只能从多个线程中得到好处。读取文件然后处理它是一个顺序操作,不能重叠。也许你可以同时做一些处理,但这对你的问题来说是不必要的。非常模糊。启动另一个后台工作程序并让第一个后台工作程序等待它完成是没有意义的。如果你能同时做一些事情,你只能从多个线程中得到好处。读取文件然后处理它是一个顺序操作,不能重叠。也许你可以同时做一些处理,但这对你的问题来说是不必要的。一个后台工作人员可以做两件或更多不同的事情。需要注意的是,如果您试图让BackgroundWorker一次做多件事,这将导致您的代码失败 下面是如何让BackgroundWorker执行多个活动的简要概述 检查后台工作人员是否正在处理某些事情。 如果它已经在工作,您必须等待它完成,或者取消当前活动,这将要求您在DoWork事件中采用不同的编码样式。 如果它不起作用,您可以安全地继续下一步。 使用指定操作的参数或参数调用BackgroundWorker的RunWorkerAsync方法。 在BackgroundWorker的DoWork事件处理程序中,检查传递的参数e.参数并执行所需的活动。 以下是一些示例代码,可供您参考:
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
翻译成这样:
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
按照以下步骤让代码在VB10之前的版本中运行
添加此代理
Delegate Sub SetTextSafelyDelegate(ByVal text As String)
然后将所有Me.InvokeSub SetTextSafelytext更改为
还要注意,在我使用匿名委托设置文本的任何地方,都必须重写代码以调用settextsafety方法
例如,bgwWorker\u DoWork的For循环部分中的行Me.InvokeSub txtResults.Text&=safeValue&vbCrLf将变为settextsafelysafeevalue&vbCrLf
如果您想了解更多关于代理的信息,请阅读以下文章(全部来自MSDN)
一个后台工作人员可以做两件或更多不同的事情。需要注意的是,如果您试图让BackgroundWorker一次做多件事,这将导致您的代码失败 下面是如何让BackgroundWorker执行多个活动的简要概述 检查后台工作人员是否正在处理某些事情。 如果它已经在工作,您必须等待它完成,或者取消当前活动,这将要求您在DoWork事件中采用不同的编码样式。 如果它不起作用,您可以安全地继续下一步。 使用指定操作的参数或参数调用BackgroundWorker的RunWorkerAsync方法。 在BackgroundWorker的DoWork事件处理程序中,检查传递的参数e.参数并执行所需的活动。 以下是一些示例代码,可供您参考:
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
翻译成这样:
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
按照以下步骤让代码在VB10之前的版本中运行
添加此代理
Delegate Sub SetTextSafelyDelegate(ByVal text As String)
然后将所有Me.InvokeSub SetTextSafelytext更改为
还要注意,在我使用匿名委托设置文本的任何地方,都必须重写代码以调用settextsafety方法
例如,bgwWorker\u DoWork的For循环部分中的行Me.InvokeSub txtResults.Text&=safeValue&vbCrLf将变为settextsafelysafeevalue&vbCrLf
如果您想了解更多关于代理的信息,请阅读以下文章(全部来自MSDN)
我不想在第一个任务结束后立即运行第二个任务,我只想在用户单击button@Smith在这种情况下,让第二个后台工作人员工作会更干净。在用户单击时,您可以检查第一个是否通过completed event或IsBusy标志完成,如果确定第一个已完成,则可以启动第二个。我不想
第一个任务结束后立即运行第二个任务,我只想在用户单击button@Smith在这种情况下,让第二个后台工作人员工作会更干净。在用户单击时,您可以检查第一个是否由completed event(已完成事件)或IsBusy(正忙)标志完成,如果您确定第一个已完成,则可以触发第二个。那么解决方案是什么,我使用bwkMain加载大文本文件,我可以使用相同的bwkMain在加载完成后处理文本文件吗?是,当然我想不出你为什么会认为这是不可能的。谢谢,那么你能帮我编写示例代码吗。请注意,要执行的两个任务是不同的。我如何判断其中一个任务是否已完成,在bwrkMain_ProgressChanged和bwrkMain_DoWork事件中,我如何根据已处理的任务执行操作?那么解决方案是什么,我使用bwkMain加载大文本文件,是否可以在完成加载后使用相同的bwkMain处理文本文件?是的,当然。我想不出你为什么会认为这是不可能的。谢谢,那么你能帮我编写示例代码吗。请注意,要执行的两个任务是不同的。我如何判断其中一个任务是否已完成,在bwrkMain_ProgressChanged和bwrkMain_DoWork事件中,我如何根据已处理的任务执行操作?如果我没有弄错,您希望使用一个BackgroundWorker执行两个或多个不同的活动,对吗?如果我没有弄错,您希望使用一个BackgroundWorker来执行两个或更多不同的活动,对吗?Me.InvokeSub中带下划线的子{expression expected}SetTextSafelytext@Smith:抱歉耽搁了。我用你问题的解决方案更新了答案。如果你还需要知道什么,请告诉我。Cheers.IDE在Me.InvokeSub中加下划线的子{expression expected}SetTextSafelytext@Smith:抱歉耽搁了。我用你问题的解决方案更新了答案。如果你还需要知道什么,请告诉我。干杯