我怎样才能用一个BackgroundWorker的做不同的活动?能用、不同、BackgroundWorker

2023-09-04 06:23:34 作者:熬过去就好了

我使用VB.NET 2005程序设计我使用的是的BackgroundWorker 加载一个大型列表或文本文件,并对其进行处理。

I am programming using VB.NET 2005. I am using a BackgroundWorker to load a large list or text file and process it.

是否有可能使用相同的背景工人来处理别的事情,即进程加载的文本文件? 财产以后像

Is it possible to use the same background worker to process something else, i.e. to process the text file that was loaded? somthing like

Dim bwkMain as New BackgroundWorker()

如果其可能的话,我该如何在相同的形式实现它,因为我已经实现了第一个?

If its possible, how do I implement it in the same form as I have already implemented for the first one?

修改 现在的问题是:是否有可能使用相同的BackgroundWorker为另一个任务,它完成一个任务后

EDIT The question is: is it possible to use the same BackgroundWorker for another task, after it finishes one task?

推荐答案

有可能有一个单个的BackgroundWorker做两个或更多个不同的事情。需要说明的是,如果你尝试有BackgroundWorker的做多件事情的时间,因为它会导致你的code失败。

It is possible to have a single BackgroundWorker do two or more different things. The caveat is that if you try to have the BackgroundWorker do more than one thing at a time as it will cause your code to fail.

下面是如何获得BackgroundWorker的做多活动的简要概述。

Here is a brief overview of how to get the BackgroundWorker to do multiple activities.

检查BackgroundWorker的不工作的东西。 如果它已经工作,你要么必须等待它完成,或取消当前活动(这将需要你采取了的DoWork 事件)。 如果它不工作,你是安全去到下一个步骤。 Check if the BackGroundWorker is not working on something. If it is already working, you'll either have to wait for it to complete or cancel the current activity (which will require you adopt a different coding style in the DoWork event). If it is not working, you're safe to go on to the next step.

下面是一些示例code,引导您完成:

Here is some sample code to guide you through:

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

这是与它去的形式:

And this is the form that goes with it:

另外还要考虑读MSDN上的以下文章:

Also consider reading the following articles on MSDN:

BackgroundWorker的:在阅读了大量关于这一类知道它的所有属性的方法,彻底事件(这不是太大的类)。 如何:使线程安全的调用到Windows窗体控件的 BackgroundWorker: Read extensively on this class and know all its properties methods and events thoroughly (it is not too big a class). How to: Make Thread-Safe Calls to Windows Forms Controls

在code以上的VB 10件作品(VS 2010)只。为了实现相同的code在其他版本的VB,你必须写一个显著金额code,因为它们不支持匿名委托。

The code above works in VB 10 (VS 2010) only. In order to implement the same code in other versions of VB, you'll have to write a significant amount of code as they do not support anonymous delegates.

在旧版本的VB,行

Public Sub Sample()
    Me.Invoke(Sub() txtResults.Text &= safeValue & vbCrLf)
End Sub

转换为这样的事情:

translates to something like this:

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

按照以下步骤获得code $ p中$ P VB工作10

Follow these steps to get the code to work in pre VB 10

添加此委托

Delegate Sub SetTextSafelyDelegate(ByVal text As String)

,然后更改所有 Me.Invoke(子()SetTextSafely(文本))

Me.Invoke(New SetTextSafelyDelegate(AddressOf SetTextSafely), text)

另外请注意,任何地方,我设置一个匿名委托的文字,你就必须重写code调用 SetTextSafely 方法。

例如,行 Me.Invoke(子()txtResults.Text和放大器; = safeValue和放大器; vbCrLf)中的for循环部分的 bgwWorker_DoWork 将成为 SetTextSafely(safeValue和放大器; vbCrLf)

For instance, the line Me.Invoke(Sub() txtResults.Text &= safeValue & vbCrLf) in the for loop section of the bgwWorker_DoWork will become SetTextSafely(safeValue & vbCrLf)

如果您想了解更多有关代表,阅读下面的文章(均来自MSDN)

If you'd like to know more about delegates, read the following articles (all from MSDN)

委托声明 如何:使线程安全的调用到Windows窗体控件的 托管线程最佳实践 Delegate Statement How to: Make Thread-Safe Calls to Windows Forms Controls Managed Threading Best Practices