- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有两个类(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/
如何显示需要同步运行的表单。我尝试从线程池的 queueworker 运行 application.run - 但有时我有一些无效的句柄。尝试使用常规线程,但是当主窗体关闭时它不会关闭它 - 我真的不
本次将要很大家分享的是一个跨平台运行的服务插件 - TaskCore.MainForm,此框架是使用.netcore来写的,现在netcore已经支持很多系统平台运行了,所以将以前的Task.Mai
我的应用程序有多种形式,还有一种更重要的形式,即主要形式,其行为通常可以,但是在相同情况下(例如,当我从子表单中打开文件对话框时),行为是:子表单被隐藏并显示主窗体。 如何避免这种情况? 最佳答案 确
连接到数据库后是否可以从“可用”表单列表中选择一个表单(作为主表单)?我有一个带有 3 个“可用”表单的数据模块。暂时没有主表单。首先创建数据模块。现在,我想根据用户登录的数据库选择表单,并将其设为主
这是 *.dpr : program Project1; uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}, Unit2 in 'Unit2.pas
我有这个 MainForm 类: namespace homework_001{ public partial class MainForm : Form { public MainForm(
这个问题在这里已经有了答案: How do I prevent the app from terminating when I close the startup form? (4 个答案) 关闭
我有以下类(class): public class CreateNewWeapon : BaseWeapon { string[] weaponNames = { "Dragonsl
在我们现有的代码中,我们有很多这样的代码,其中以 MainForm 作为所有者(例如,而不是 nil)创建表单,但我们显式地释放它。 function SomeFunc(): Boolean; var
如何从后台任务向主窗体发送消息 (TOmniMessage)? 我想向 Mainform 发送以下消息: Memo1.Lines.Add(Format('BEGIN: %s', [msg.MsgDat
我想在我的 Mainform 上制作面板的屏幕截图。这个屏幕截图应该是在用户在子表单上选择了一些选项之后制作的。一开始一切顺利,但现在屏幕截图包含部分子表单。 子表单像这样打开: private vo
我正在使用 Borland c++ builder。我有一个应用程序,我希望隐藏主表单,直到在不同的表单上按下按钮。我已经将主窗体上的 Visible 值设置为 false,但是当我运行程序时它仍然显
当我将 TRibbon 控件放置在不是应用程序 MainForm 的窗体上时,TRibbon 的操作(即剪切、粘贴)将始终在执行操作后将焦点返回到 MainForm。 即使保存 TRibbon 的 T
我有一个导出 DLL 并具有 library header 的 Delphi 2010 应用程序。它在 TThread 中创建其 MainForm,如下所示: var ActiveThread:
我对编程还很陌生,并且已经开始了一个项目,我试图将程序的功能分成类,每个类处理与程序的特定部分相关的大部分内容。 我有一个名为 DirectoryMonitors 的类,它创建一个对象来监视带有 Fi
我有一个 MainForm 类,我有一个函数来检索存储在我的数据库中的设置。 到现在为止还挺好。 然后,我有一个在启动时加载的插件 (DLL),但我想使用相同的函数来检索我的 DLL 中的设置。 如果
我可以在不引用构造函数中的对象的情况下执行此操作吗?也就是说,任何继承自FrmTaoChild的类在创建时都必须在主窗口的工具栏上添加按钮 public class FrmTaoMain extend
我正在尝试在 MainForm 的 datagridview 中显示数据。我正在创建客户表单中添加客户。 private void createButton_Click(object sender,
我的应用程序使用 Message.hpp 中的 SendStructMessage() 函数通过传入消息填充一些面板。 SendStructMessage() 需要一个有效的窗口句柄才能发送到。 我已
我有两个类(class)。 Public Class MainForm Private Project As clsProject Private Sub btnDo_Click ..
我是一名优秀的程序员,十分优秀!