在尝试实现一个简单的 BackgroundWorker 时,我遇到了臭名昭著的“跨线程操作无效”异常。我花了几个小时阅读我能找到的关于这个主题的所有内容,包括关于 SO 的许多相关问题,但我就是不明白。
我有一个简单的 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 加载项的一部分。我在功能区 Load 事件中实例化我的表单,然后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
移至mProcessing = New MyForm()
Click 处理程序可消除异常。一切运作良好。我多次来回移动代码,并对问题/解决方案充满信心。