Как отследить несколько завершенных операций BackgroundworkerX.Runworker - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь использовать один обработчик, чтобы покрыть конец нескольких действий фонового работника, и не могу найти способ получить информацию о конкретном фоновом работнике с помощью события 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

В разделе «Работать здесь» ничего нет, потому что я не знаю, как перехватить данные, и не смог найти подробную информацию об идентификаторе события backgroundworkercompleted.

Пожалуйста - любые указания относительно того, как я могу определить конкретный завершенный BackgroundWorker

1 Ответ

0 голосов
/ 12 ноября 2018

Как и во всех обработчиках событий, параметр sender является ссылкой на объект, вызвавший событие, поэтому вы можете получить доступ к фактическому BackgroundWorker, который завершил свою работу через него. Если вам нужны другие данные, вы назначаете их свойству e.Result в обработчике событий DoWork и возвращаете их из свойства e.Result в обработчике событий RunWorkerCompleted. e.Result работает для получения данных из обработчика событий DoWork так же, как e.Argument работает для получения данных.

Проверьте этот для некоторых примеров использования BackgroundWorker объектов, включая передачу данных с использованием e.Result. Вы также можете проверить мой собственный BackgroundMultiWorker класс , который в основном объединяет функциональность нескольких объектов BackgroundWorker в один объект BackgroundMultiWorker. Он идентифицирует каждую задачу с помощью токена.

EDIT:

Вот пример, который может помочь с этой проблемой и вашей задачей в целом:

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
...