Ошибки фонового работника - PullRequest
0 голосов
/ 21 января 2019

Backgroundworker Я пытаюсь реализовать BackgroundWorker в своем коде vb.net. Я понимаю, что вы не можете обновить пользовательский интерфейс из фонового рабочего. Так как при установке точек останова в моем коде в подпрограмме Backgroundworker.DoWork я бы получил Me.Accessibility.Object сгенерировал исключение типа 'System.InvalidOperationException' Сообщение «Операция между потоками недопустима: доступ к элементу управления FrmLoad осуществляется из потока, отличного от потока, в котором он был создан».

Чтобы попытаться понять, почему это происходит, я ТОЧНО скопировал код из https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.7.2 и при повторной установке точек останова в подпрограмме DoWork я получаю то же исключение. Я пробовал несколько других примеров кода Microsoft с той же проблемой. Что-то не так с кодом?

Imports System
Imports System.ComponentModel
Imports System.Windows.Forms

Namespace BackgroundWorkerSimple
    Public Partial Class Form1
        Inherits Form

        Public Sub New()
            InitializeComponent()
            backgroundWorker1.WorkerReportsProgress = True
            backgroundWorker1.WorkerSupportsCancellation = True
        End Sub

        Private Sub startAsyncButton_Click(ByVal sender As Object, ByVal e As EventArgs)
            If backgroundWorker1.IsBusy <> True Then
                backgroundWorker1.RunWorkerAsync()
            End If
        End Sub

        Private Sub cancelAsyncButton_Click(ByVal sender As Object, ByVal e As EventArgs)
            If backgroundWorker1.WorkerSupportsCancellation = True Then
                backgroundWorker1.CancelAsync()
            End If
        End Sub

        Private Sub backgroundWorker1_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
            Dim worker As BackgroundWorker = TryCast(sender, BackgroundWorker)

            For i As Integer = 1 To 10

                If worker.CancellationPending = True Then
                    e.Cancel = True
                    Exit For
                Else
                    System.Threading.Thread.Sleep(500)
                    worker.ReportProgress(i * 10)
                End If
            Next
        End Sub

        Private Sub backgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
            resultLabel.Text = (e.ProgressPercentage.ToString() & "%")
        End Sub

        Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
            If e.Cancelled = True Then
                resultLabel.Text = "Canceled!"
            ElseIf e.[Error] IsNot Nothing Then
                resultLabel.Text = "Error: " & e.[Error].Message
            Else
                resultLabel.Text = "Done!"
            End If
        End Sub
    End Class
    End Namespace

Это на самом деле не мешает запуску кода, но я хочу убедиться, что поток действительно остается безопасным.

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Этот пример кода написан на C #, и вы, очевидно, не указали функцию и ее вызов:

    // Set up the BackgroundWorker object by 
    // attaching event handlers. 
    private void InitializeBackgroundWorker()
    {
        backgroundWorker1.DoWork += 
            new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerCompleted += 
            new RunWorkerCompletedEventHandler(
        backgroundWorker1_RunWorkerCompleted);
        backgroundWorker1.ProgressChanged += 
            new ProgressChangedEventHandler(
        backgroundWorker1_ProgressChanged);
    }

Хотя это можно переписать с помощью addhandler, vbish способ сделать это - добавить предложение handles в объявление вашего метода.

0 голосов
/ 22 января 2019

Я считаю, что это то, что вы ищете:

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        InitializeComponent()
        BackgroundWorker1.WorkerReportsProgress = True
        BackgroundWorker1.WorkerSupportsCancellation = True
    End Sub

    Private Sub startAsyncButton_Click(sender As Object, e As EventArgs) Handles btn_Start.Click
        If Not BackgroundWorker1.IsBusy Then
            BackgroundWorker1.RunWorkerAsync()
        End If
    End Sub

    Private Sub cancelAsyncButton_Click(sender As Object, e As EventArgs) Handles btn_Cancel.Click
        If BackgroundWorker1.WorkerSupportsCancellation = True Then
            BackgroundWorker1.CancelAsync()
        End If
    End Sub



    Private Sub backgroundWorker1_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        'Dim worker As BackgroundWorker = TryCast(sender, BackgroundWorker)
        For i As Integer = 1 To 10
            If Not BackgroundWorker1.CancellationPending Then
                System.Threading.Thread.Sleep(500)
                BackgroundWorker1.ReportProgress(i * 10)
            Else
                e.Cancel = True
                Exit For
            End If
        Next
    End Sub

    Private Sub backgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        resultLabel.Text = (e.ProgressPercentage.ToString() & "%")
    End Sub

    Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        If e.Cancelled = True Then
            resultLabel.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            resultLabel.Text = "Error: " & e.[Error].Message
        Else
            resultLabel.Text = "Done!"
        End If
    End Sub

Главное, что выглядело так, как будто вам не хватало, было событие Handles для Background1.ProgressChanged

...