我正在开发一个VB.Net项目,我正在尝试从一个在后台运行的线程(一个必要的邪恶)中为我的表单添加一个标签。
我创建了全局变量SmallTextLabel(Type:Label)并分配了我想要的所有属性。我现在只是想使用Me.Controls.Add(SmallTextLabel)将其添加到我的表单中。每次运行此代码时,它都会告诉我必须调用控件。我在屏幕上尖叫,这就是我正在尝试做的事情,但它会听吗?!
无论如何,我在过去的4个小时里一直在搜索互联网,并且还没有设法解决这个问题,所以请...那里的任何人都可以为我发光吗?
这是我目前使用AddSmallLabelControl(SmallTextLabel)调用的代码
修改后的示例
Private Delegate Sub AddSmallLabelControlHandler(ByVal test As Label)
Private Sub AddSmallLabelControl(ByVal test As Label)
If Me.InvokeRequired Then
Dim d As New AddSmallLabelControlHandler(AddressOf AddSmallLabelControl)
Me.Invoke(d, test)
Else
Me.Controls.Add(test)
test.BringToFront()
End If
End Sub
Private Sub ShowScanConfirmationLabel()
Dim SmallTextLabel As New Label
Dim TahomaSmall As New Font("Tahoma", 20, FontStyle.Bold)
With SmallTextLabel
.Height = 40
.Width = 312
.Location = New Point(3, 121)
.BackColor = Color.Green
.Text = "Testing"
.TextAlign = ContentAlignment.TopCenter
.Font = TahomaSmall
End With
End With
Call AddSmallLabelControl(SmallTextLabel)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim MakeLabelsVisibleHandler As New ThreadStart(AddressOf MakeLabelsVisible)
Dim timerThread As New Thread(MakeLabelsVisibleHandler)
timerThread.Start()
End Sub
Private Sub MakeLabelsVisible()
ShowScanConfirmationLabel()
End Sub
答案 0 :(得分:2)
好的,我在您的代码中发现了一点但严重的不一致,这可能会导致您实际上没有运行调用......
假设您在工作线程中初始化Label,那么检查Me.SmallLabel.InvokeRequired
将返回False,因为它已在同一个线程上创建。因此,您的程序实际上永远不会调用Me.Invoke(...)
当您尝试访问在另一个线程上创建的表单控件时,应检查该表单是否需要调用。在您的情况下:Me.InvokeRequired
请尝试使用此代码:
Private Delegate Sub AddSmallLabelControlHandler(ByVal test As Label)
Private Sub AddSmallLabelControl(ByVal test As Label)
If Me.InvokeRequired Then
Dim d As New AddSmallLabelControlHandler(AddressOf AddSmallLabelControl)
Me.Invoke(d, test)
Else
Me.Controls.Add(test)
' If you need .BringToFront use it here:
test.BringToFront()
' But like this it is called every time you add a label of course.
End If
End Sub
修改强>
关于.NET CF
因此,紧凑型框架上的某些独特方式似乎Invoke
表现。即,它希望调用EventHandler
和别无其他。
来源:MSDN
在这种情况下,我们必须重构我们的代码:
首先,因为我们必须使用EventHandler
,我们需要使用它的签名EventHandler(Object sender, EventArgs e)
因此,当我们需要向目标程序发送一个新的Label
时,一个简单的解决方案是将其放入sender
并随后进行转换。
但谨慎的做法是实现自己的EventArgs
类,其中包含一个Control
并投射该类。
所以这里示例代码的VB变体显示了如何调用CF上的控件
' Start the worker thread
Private Sub InitWorker()
Dim trdWorker As New Thread(New ThreadStart(AddressOf WorkerThread))
trdWorker.Start()
End Sub
Private Sub WorkerThread()
Dim testLabel As New Label() With {
.Name = "TestLabel",
.Text = "Test Label",
.Location = New Point(5, 30)
}
' Create your EventArgs containing the control you wish to add
Dim e As New AddControlEventArgs(testLabel)
' Create EventHandler
Dim ehnd As New EventHandler(AddressOf AddControl)
' Invoke EventHandler with EventArgs (don't need sender as of now)
Me.Invoke(ehnd, Nothing, e)
End Sub
' Define your custom EventArgs to hold one Control
Public Class AddControlEventArgs : Inherits EventArgs
Public Sub New(p_control As Control)
m_control = p_control
End Sub
Private m_control As Control
Public ReadOnly Property Control As Control
Get
Return m_control
End Get
End Property
End Class
Private Sub AddControl(sender As Object, e As EventArgs)
' Cast EventArgs to your custom EventArgs
Dim ec As AddControlEventArgs = DirectCast(e, AddControlEventArgs)
Me.Controls.Add(ec.Control)
' Still, do you need this?
ec.Control.BringToFront()
End Sub
最后的一些说明:
我的解决方案与MSDN源中的解决方案有一个基本方式不同。
MSDN解决方案存储它希望在类中的中性字段上调用的消息,我创建自己的EventArgs来保存消息(在我们的案例a Control
)
我没有安装CF环境,因此我无法在CF环境中测试解决方案 。有一些反馈会很棒,这是否真的解决了这个问题
您应该使用compact-framework
标记您的帖子,因为CF上的解决方案可能与普通解决方案有根本的不同(由此困境证明)
答案 1 :(得分:0)
通过在调用中移动标签的创建,代码运行没有问题。感谢@MrPaulch对此问题的所有帮助。请问你最后的评论。
Private Delegate Sub AddSmallLabelControlHandler(ByVal test As String)
Private Sub AddSmallLabelControl(ByVal test As String)
If Me.InvokeRequired Then
Dim d As New AddSmallLabelControlHandler(AddressOf AddSmallLabelControl)
Me.Invoke(d, test)
Else
Dim SmallTextLabel As New Label
Dim TahomaSmall As New Font("Tahoma", 20, FontStyle.Bold)
With SmallTextLabel
.Height = 40
.Width = 312
.Location = New Point(3, 121)
.BackColor = Color.Green
.Text = test
.TextAlign = ContentAlignment.TopCenter
.Font = TahomaSmall
End With
Me.Controls.Add(SmallTextLabel)
test.BringToFront()
End If
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim MakeLabelsVisibleHandler As New ThreadStart(AddressOf MakeLabelsVisible)
Dim timerThread As New Thread(MakeLabelsVisibleHandler)
timerThread.Start()
End Sub
Private Sub MakeLabelsVisible()
Call AddSmallLabelControl("This now works")
End Sub