您正在尝试修改控件的属性,该属性驻留在与您调用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