Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 后台工作线程问题_.net_Vb.net_Winforms_Backgroundworker - Fatal编程技术网

.net 后台工作线程问题

.net 后台工作线程问题,.net,vb.net,winforms,backgroundworker,.net,Vb.net,Winforms,Backgroundworker,在尝试实现一个简单的BackgroundWorker时,我遇到了臭名昭著的“Cross thread operation not valid”异常。我花了几个小时阅读了我能找到的关于这个主题的所有东西,包括许多相关的问题,但我就是不明白 我有一个简单的winform,它有一个DoWork()方法: 它需要一个代表要完成的工作的委托 它创建一个BackgroundWorker,并将委托分配给DoWork事件 它调用RunWorkerAsync() RunWorkerCompleted()调用的函数

在尝试实现一个简单的BackgroundWorker时,我遇到了臭名昭著的“Cross thread operation not valid”异常。我花了几个小时阅读了我能找到的关于这个主题的所有东西,包括许多相关的问题,但我就是不明白

我有一个简单的winform,它有一个DoWork()方法:

  • 它需要一个代表要完成的工作的委托
  • 它创建一个
    BackgroundWorker
    ,并将委托分配给
    DoWork
    事件
  • 它调用
    RunWorkerAsync()
  • RunWorkerCompleted()
    调用的函数尝试更新表单上的标签,但引发跨线程异常

    Public Class MyForm
    
        Public Sub DoWork(workToDo As DoWorkEventHandler)
            Dim worker As New BackgroundWorker()
            worker.WorkerReportsProgress = True
            worker.WorkerSupportsCancellation = True
            AddHandler worker.DoWork, workToDo
            AddHandler worker.RunWorkerCompleted, AddressOf WorkerCompleted
            worker.RunWorkerAsync()
        End Sub
    
        Private Sub WorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
            resultLabel.Text = "Done!" ' Exception thrown here
        End Sub
    
    End Class
    
    因此,看起来
    WorkerCompleted
    正在后台线程上运行。我是否接近一个有效的解决方案,或者我没有掌握基本原理

    更新:一个神秘的补丁 我发现了一个愚蠢的运气。我们得进一步查一下申请表。这是VSTO Excel加载项的一部分。我正在功能区加载事件中实例化表单,然后在单击按钮时调用
    Show()
    。这引发了一个例外

    Private Sub Ribbon1Load(ByVal sender As System.Object, ByVal e As RibbonUIEventArgs) Handles MyBase.Load
        mProcessing = New MyForm()
    End Sub 
    
    Private Sub Button1Click(sender As System.Object, e As RibbonControlEventArgs) Handles Button1.Click
        mProcessing.Show()
        mProcessing.DoWork(AddressOf UpdateData)
    End Sub
    

    mpprocessing=New MyForm()
    移动到单击处理程序可消除异常。一切进展顺利。我来回移动了几次代码,并对问题/解决方案充满信心

    RunWorkerCompleted事件通常与
    BackgroundWorker
    本身(UI线程)在同一线程上运行,因此我怀疑这是问题所在。我怀疑您的错误是在
    DoWork
    方法中发生的,只是在您点击UI线程时被抛出。国家:

    在访问RunWorkerCompletedEventArgs.Result属性之前,RunWorkerCompletedEventArgs.Error和AsyncCompletedEventArgs.Cancelled属性应始终检查。如果引发异常或操作被取消,访问RunWorkerCompletedEventArgs.Result属性将引发异常

    Private Sub Ribbon1Load(ByVal sender As System.Object, ByVal e As RibbonUIEventArgs) Handles MyBase.Load
        mProcessing = New MyForm()
    End Sub 
    
    Private Sub Button1Click(sender As System.Object, e As RibbonControlEventArgs) Handles Button1.Click
        mProcessing.Show()
        mProcessing.DoWork(AddressOf UpdateData)
    End Sub
    
    如果您遇到UI线程上未运行的
    RunWorkerCompleted
    事件的问题,则您可以始终使用
    invoke
    调用UI更新以在正确的线程上运行,例如

    resultLabel.Invoke(Sub() resultLabel.Text = "Done!")
    

    我看不出有什么不对劲,但这是可能发生的。我没怎么见过,但我见过,不得不这样处理:

    If Me.InvokeRequired Then
        Me.BeginInvoke(Sub() resultLabel.Text = "Done!")
    Else
        resultLabel.Text = "Done!"
    End If
    

    对我有用。请举例说明这个问题。@Steven:我偶然发现了一个解决方案。请参阅我的更新。一般诊断是,当功能区的加载事件触发时,System.Threading.SynchronizationContext.Current为Nothing。您可以使用调试器检查的内容。这是非常不健康的,指向一个更大的潜在问题,一个你不应该忽视的问题;我只是在发帖时删减了代码。查看我的更新。