gpt4 book ai didi

vb.net - 使用来自另一个类的 backgroundworker 从 mainform 类更新标签

转载 作者:行者123 更新时间:2023-12-04 02:41:04 26 4
gpt4 key购买 nike

我有两个类(class)。

Public Class MainForm

Private Project As clsProject


Private Sub btnDo_Click
...
Backgroundworker.RunWorkerAsync()

End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork


Project = New clsProject


End Sub

和 MainForm 中的两个方法

 Public Shared Sub setLabelTxt(ByVal text As String, ByVal lbl As Label)
If lbl.InvokeRequired Then
lbl.Invoke(New setLabelTxtInvoker(AddressOf setLabelTxt), text, lbl)
Else
lbl.Text = text
End If
End Sub
Public Delegate Sub setLabelTxtInvoker(ByVal text As String, ByVal lbl As Label)
end class

我想从 clsProject 构造函数更新 MainForm 的标签。

 MainForm.setLabelTxt("Getting prsadasdasdasdasdry..", MainForm.lblProgress)

但它不会更新它们。我做错了什么?

最佳答案

问题是您正在使用全局 MainForm 实例在此处的后台线程中访问标签:

Public Class clsProject
Public Sub New()
' When accessing MainForm.Label1 on the next line, it causes an exception
MainForm.setLabelTxt("HERE!", MainForm.Label1)
End Sub
End Class

可以调用MainForm.setLabelTxt,因为那是一个共享方法,所以不会通过全局实例来调用它。但是,当您访问 Label1 属性时,这是在利用 VB.NET 的诡计来访问窗体的全局实例。在非 UI 线程中显然不允许通过自动全局实例变量(它始终与类型共享相同的名称)使用表单。当您这样做时,它会抛出 InvalidOperationException,并显示以下错误消息:

An error occurred creating the form. See Exception.InnerException for details. The error is: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.

我猜你没有看到错误的原因是你在某处捕获了异常而你只是忽略了它。如果您停止使用该全局实例变量,错误就会消失并且它会起作用。例如,如果您将构造函数更改为:

Public Class clsProject
Public Sub New(f As MainForm)
' The next line works because it doesn't use the global MainForm instance variable
MainForm.setLabelTxt("HERE!", f.Label1)
End Sub
End Class

然后,在您的 MainForm 中,您必须这样调用它:

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Project = New clsProject(Me) ' Must pass Me
End Sub

从后台线程使用全局实例是不允许的,但是当我们从后台线程使用相同的标签时,不通过那个全局变量它就可以工作。

很明显,您不能在后台线程中使用全局 MainForm 变量,但可能不清楚的是,永远不要使用它是个坏主意。首先,它令人困惑,因为它与 MainForm 类型共享相同的名称。但更重要的是,它是一个全局变量,如果可以避免,任何类型的全局状态几乎总是不好的做法。

虽然上面的示例确实解决了问题,但它仍然是一种很糟糕的实现方式。更好的选择是将 setLabelTxt 方法传递给 clsProject 对象,或者更好的做法是让 clsProject 在标签需要时简单地引发一个事件被改变。然后,MainForm 可以简单地监听这些事件并在它们发生时进行处理。最终,clsProject 类可能是某种业务类,无论如何都不应该执行任何类型的 UI 工作。

关于vb.net - 使用来自另一个类的 backgroundworker 从 mainform 类更新标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19929331/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com