.net 如何使用一个后台工作人员进行不同的活动?

.net 如何使用一个后台工作人员进行不同的活动?,.net,vb.net,backgroundworker,.net,Vb.net,Backgroundworker,我正在使用VB.NET2005编程。我正在使用BackgroundWorker加载一个大列表或文本文件并对其进行处理 是否可以使用相同的后台工作程序处理其他内容,即处理加载的文本文件? 糟糕的 Dim bwkMain as New BackgroundWorker() 如果可能的话,我如何以与第一个版本相同的形式实现它 编辑 问题是:在完成一项任务后,是否可以将同一个BackgroundWorker用于另一项任务?由于无法并行运行两项任务,因此可以在同一个BackgroundWorker中按如

我正在使用VB.NET2005编程。我正在使用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:抱歉耽搁了。我用你问题的解决方案更新了答案。如果你还需要知道什么,请告诉我。干杯