Public Sub Rename(ByVal labelno As Integer)
Try
Dim lbl As New Label
lbl = Controls("Label" & labelno.ToString())
lbl.Text = ReceivedFrame.ToString()
Catch ex As Exception
MessageBox.Show(ex.Message.ToString())
End Try
我想将标签文本从1更改为50.标签号不作为输入。我尝试了上面的代码。它在其他项目中工作。但在我当前的项目中,它不起作用错误显示为这样(交叉线程操作不是有效的.control label1从一个线程访问,而不是它创建的线程),我想更改标签文本only.label& Label我验证了没有正常工作。有什么其他方法可以在vb.net中重命名标签吗?
答案 0 :(得分:0)
您正在尝试修改控件的属性,该控件驻留在与您调用Rename()
的线程不同的线程上。更新控件时,您应检查是否需要将调用发送到相应的线程,或者"调用"电话。这应该有用。
方法1:始终调用
Public Sub Rename(ByVal labelno As Integer)
Try
Dim lbl As New Label
lbl = Controls("Label" & labelno.ToString())
lbl.Invoke(Sub() lbl.Text = ReceivedFrame.ToString())
Catch ex As Exception
MessageBox.Show(ex.Message.ToString())
End Try
End Sub
它将始终调用该调用,这在从控件的线程调用Rename()
时会产生不必要的代价。但它应该始终有效。您也可以这样做,只在需要时调用,以便不对UI线程进行不必要的调用。
方法2:仅在需要时调用
Public Sub Rename(ByVal labelno As Integer)
Try
Dim lbl As New Label
lbl = Controls("Label" & labelno.ToString())
changeLabelText(lbl, ReceivedFrame.ToString())
Catch ex As Exception
MessageBox.Show(ex.Message.ToString())
End Try
End Sub
Private Delegate Sub changeLabelDel(lbl As Label, txt As String)
Private Sub changeLabelText(lbl As Label, txt As String)
If lbl.InvokeRequired Then
lbl.Invoke(New changeLabelDel(AddressOf ChangeLabelText), lbl, txt)
Else
lbl.Text = txt
End If
End Sub
哦,还有一件事。您可以自动执行整个调用所需的检查以供将来使用。将扩展方法放在模块中
方法3:自动调用所需的模式,可重用的代码
<Extension() _
Public Sub InvokeIfRequired(ByVal c As Control, mi As MethodInvoker)
If c.InvokeRequired Then
c.Invoke(mi)
Else
mi()
End If
End Sub
并称之为:
Public Sub Rename(ByVal labelno As Integer)
Try
Dim lbl As New Label
lbl = Controls("Label" & labelno.ToString())
lbl.InvokeIfRequired(Sub() lbl.Text = ReceivedFrame.ToString())
Catch ex As Exception
MessageBox.Show(ex.Message.ToString())
End Try
End Sub
本网站上有关于此主题的大量信息。参见
What does 'InvokeRequired' and 'Invoke' mean in .Net?
VB.net, Invoke, delegates, and threading. Can't figure out how to use them across classes