【问题标题】:Backgroundworker Errors后台工作者错误
【发布时间】:2019-01-21 20:01:34
【问题描述】:

我正在尝试在我的 vb.net 代码中实现 BackgroundWorker。我了解您无法从后台工作人员更新 UI。因为当我在 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 子中再次设置断点时,我得到了同样的异常。我已经尝试了其他几个具有相同问题的微软代码示例。代码有问题吗?

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

它实际上并没有阻碍代码运行,但我想确保线程实际上保持安全。

【问题讨论】:

  • 我无法使用此代码重现任何异常。无论我放置调试停止,它都会愉快地停止。
  • 听起来您的项目或系统中的某些内容已损坏。我会尝试创建一个新项目并尽可能少地进行更改以尝试运行此代码。如果它仍然行为不端,请尽可能在另一台机器上尝试相同的操作。获取异常的堆栈跟踪也可能会有所帮助,这样您就可以准确地看到它发生的位置。
  • 我之前忘了说 - 原始代码是 C#。我尝试为 C# 和 .Net 版本的 bot 构建一个新项目 - 仍然是同一个问题。我现在不能尝试另一台计算机,因为有许可证的同事不在。我确实尝试按照 jmoreno 的建议添加处理程序,并确保如 Michael Royston 所指出的那样包含 ProgressChanged 事件处理程序。还是没有变化。只是想解决这个问题。

标签: vb.net backgroundworker


【解决方案1】:

该示例代码是用 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 重写,但最常见的方法是在方法声明中添加句柄子句。

【讨论】:

    【解决方案2】:

    我相信这就是您正在寻找的:

        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
    

    看起来你缺少的主要是 Background1.ProgressChanged 的​​ Handles 事件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多