如何跟踪多个BackgroundworkerX.Runworker已完成的操作



我正试图使用单个处理程序来覆盖多个后台工作人员活动的结束,但找不到使用backgroundworkercompleted事件获取有关特定后台工作人员的信息的方法。我捕捉事件的代码如下:

Private Sub BGx_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted, BackgroundWorker2.RunWorkerCompleted, BackgroundWorker3.RunWorkerCompleted, BackgroundWorker4.RunWorkerCompleted, BackgroundWorker5.RunWorkerCompleted, BackgroundWorker6.RunWorkerCompleted, BackgroundWorker7.RunWorkerCompleted, BackgroundWorker8.RunWorkerCompleted
'Do work here based on completed Backgroundworker
For BG = 1 To 8
If Not DSWorkers(BG).IsBusy Then
If DStatus(BG) = -2 Then : DStatus(BG) = -1 : End If
End If
Next
Complete()
End Sub

"在这里工作"部分没有任何内容,因为我不知道如何捕捉,也无法找到后台工作人员完成事件id的详细信息。

请-任何关于我如何识别特定完成的BackgroundWorker 的指针

与所有事件处理程序一样,sender参数是对引发事件的对象的引用,因此您可以通过它访问已完成工作的实际BackgroundWorker。如果您需要其他数据,则将其分配给DoWork事件处理程序中的e.Result属性,然后从RunWorkerCompleted事件处理程序的e.Result属性取回。e.Result用于从DoWork事件处理程序中获取数据,就像e.Argument用于从中获取数据一样

有关使用BackgroundWorker对象的一些示例,包括使用e.Result传递数据,请查看此部分。您可能还想签出我自己的BackgroundMultiWorker类,该类基本上将多个BackgroundWorker对象的功能组合为一个BackgroundMultiWorker对象。它使用令牌标识每个任务。

编辑:

以下是一个可能有助于解决此问题和您的任务的示例:

Imports System.ComponentModel
Imports System.Threading
Public Class Form1
Private ReadOnly resultsByWorker As New Dictionary(Of BackgroundWorker, BackgroundWorkerResult)
Private ReadOnly rng As New Random
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'The NumericUpDown is used to select the index of a BackgroundWorker to cancel.
With NumericUpDown1
.DecimalPlaces = 0
.Minimum = 0
.Maximum = 9
End With
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create 10 BackgroundWorkers and run them.
For i = 1 To 10
Dim worker As New BackgroundWorker
resultsByWorker.Add(worker, New BackgroundWorkerResult)
AddHandler worker.DoWork, AddressOf workers_DoWork
AddHandler worker.RunWorkerCompleted, AddressOf workers_RunWorkerCompleted
worker.WorkerSupportsCancellation = True
worker.RunWorkerAsync()
Next
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim index = Convert.ToInt32(NumericUpDown1.Value)
Dim worker = resultsByWorker.Keys.ToArray()(index)
If worker.IsBusy Then
'Cancel the BackgroundWorker at the specified index.
worker.CancelAsync()
End If
End Sub
Private Sub workers_DoWork(sender As Object, e As DoWorkEventArgs)
Dim worker = DirectCast(sender, BackgroundWorker)
'Do work for a random number of seconds between 10 and 20.
Dim period = rng.Next(10, 20 + 1)
For i = 0 To period
If worker.CancellationPending Then
e.Cancel = True
Return
End If
'Simulate work.
Thread.Sleep(1000)
Next
'The work was completed without being cancelled.
e.Result = period
End Sub
Private Sub workers_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
Dim worker = DirectCast(sender, BackgroundWorker)
Dim result = resultsByWorker(worker)
If e.Cancelled Then
result.WasCancelled = True
Else
result.Result = CInt(e.Result)
End If
Dim workers = resultsByWorker.Keys.ToArray()
If Not workers.Any(Function(bgw) bgw.IsBusy) Then
'All work has completed so display the results.
Dim results As New List(Of String)
For i = 0 To workers.GetUpperBound(0)
worker = workers(i)
result = resultsByWorker(worker)
results.Add($"Worker {i} {If(result.WasCancelled, "was cancelled", $"completed {result.Result} iterations")}.")
Next
MessageBox.Show(String.Join(Environment.NewLine, results))
End If
End Sub
End Class
Public Class BackgroundWorkerResult
Public Property WasCancelled As Boolean
Public Property Result As Integer
End Class

这是一个被修改为使用BackgroundMultiWorker的单个实例而不是BackgroundWorker类的多个实例的例子。

Imports System.Threading
Public Class Form1
Private WithEvents worker As New BackgroundMultiWorker With {.WorkerSupportsCancellation = True}
Private ReadOnly results(9) As BackgroundWorkerResult
Private ReadOnly rng As New Random
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'The NumericUpDown is used to select the index of a BackgroundWorker to cancel.
With NumericUpDown1
.DecimalPlaces = 0
.Minimum = 0
.Maximum = results.GetUpperBound(0)
End With
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create 10 BackgroundWorkers and run them.
For i = 0 To results.GetUpperBound(0)
results(i) = New BackgroundWorkerResult
worker.RunWorkerAsync(i)
Next
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim index = Convert.ToInt32(NumericUpDown1.Value)
If worker.IsBusy(index) Then
'Cancel the BackgroundWorker at the specified index.
worker.CancelAsync(index)
End If
End Sub
Private Sub worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles worker.DoWork
'Do work for a random number of seconds between 10 and 20.
Dim period = rng.Next(10, 20 + 1)
For i = 0 To period
If worker.IsCancellationPending(e.Token) Then
e.Cancel = True
Return
End If
'Simulate work.
Thread.Sleep(1000)
Next
'The work was completed without being cancelled.
e.Result = period
End Sub
Private Sub workers_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted
Dim result = results(CInt(e.Token))
If e.Cancelled Then
result.WasCancelled = True
Else
result.Result = CInt(e.Result)
End If
If Not worker.IsBusy() Then
'All work has completed so display the results.
Dim output As New List(Of String)
For i = 0 To results.GetUpperBound(0)
result = results(i)
output.Add($"Task {i} {If(result.WasCancelled, "was cancelled", $"completed {result.Result} iterations")}.")
Next
MessageBox.Show(String.Join(Environment.NewLine, output))
End If
End Sub
End Class
Public Class BackgroundWorkerResult
Public Property WasCancelled As Boolean
Public Property Result As Integer
End Class

最新更新