VB.net尝试从单独的线程访问UI元素无效
我有一个富文本框在我的主要,我想写东西,从不同的线程。我曾尝试使用调用来实现这一点,但似乎无法使其正常工作。如果我尝试使用:VB.net尝试从单独的线程访问UI元素无效,vb.net,multithreading,Vb.net,Multithreading,我有一个富文本框在我的主要,我想写东西,从不同的线程。我曾尝试使用调用来实现这一点,但似乎无法使其正常工作。如果我尝试使用: If InvokeRequired Then Dim Dgate As writeLogDelegate = New writeLogDelegate(AddressOf writeLog) BeginInvoke(Dgate, New Object() {Message}) Else RTB_Log.AppendText(Message) End
If InvokeRequired Then
Dim Dgate As writeLogDelegate = New writeLogDelegate(AddressOf writeLog)
BeginInvoke(Dgate, New Object() {Message})
Else
RTB_Log.AppendText(Message)
End If
然后InvokeRequired不会像它应该返回的那样返回true
,检查句柄是否已创建会返回false
,但是在表单加载时,如果我得到IsHandleCreated的值,它会返回true
。我尝试调用write的方法如下:
线程类代码段:
Public Sub startClientPoll(ByRef Sender As TcpListener)
Dim TThread As New Thread(New ParameterizedThreadStart(AddressOf pollClientConnect))
TThread.Start(Sender)
End Sub
Private Sub pollClientConnect(tcplistener As TcpListener)
Do
If tcplistener.Pending() Then
'MessageBox.Show("")
RaiseEvent clientConnecting()
End If
Loop Until Ended = True
End Sub
Private Sub client_Connect() Handles listenerSocket.clientConnecting
Form1.writeLog("New client awaiting accept" & vbNewLine)
Dim clientSocket As TcpClient = listenerSocket.AcceptTcpClient()
Dim clientHandler As New MPClientReciever(clientSocket)
End Sub
事件处理程序类代码段:
Public Sub startClientPoll(ByRef Sender As TcpListener)
Dim TThread As New Thread(New ParameterizedThreadStart(AddressOf pollClientConnect))
TThread.Start(Sender)
End Sub
Private Sub pollClientConnect(tcplistener As TcpListener)
Do
If tcplistener.Pending() Then
'MessageBox.Show("")
RaiseEvent clientConnecting()
End If
Loop Until Ended = True
End Sub
Private Sub client_Connect() Handles listenerSocket.clientConnecting
Form1.writeLog("New client awaiting accept" & vbNewLine)
Dim clientSocket As TcpClient = listenerSocket.AcceptTcpClient()
Dim clientHandler As New MPClientReciever(clientSocket)
End Sub
主要表单代码段:
Public Sub writeLog(ByVal Message As String)
If Not IsHandleCreated Then
CreateControl()
End If
If InvokeRequired Then
Dim Dgate As writeLogDelegate = New writeLogDelegate(AddressOf writeLog)
BeginInvoke(Dgate, New Object() {Message})
Else
RTB_Log.AppendText(Message)
End If
End Sub
您可以在类上全局定义子类,如下所示:
Private Delegate Sub AddText_DL(ByVal txtControl As Control, ByVal txtVAL As String, ByVal append As Boolean)
Private Sub AddText(ByVal txtControl As Control, ByVal txtVAL As String, ByVal append As Boolean)
If txtControl.InvokeRequired = True Then
Dim progDel As New AddText_DL(AddressOf AddText)
Dim parameters(2) As Object
parameters(0) = txtControl
parameters(1) = txtVAL
parameters(2) = append
txtControl.Invoke(progDel, parameters)
Else
If append = True Then
txtControl.text &= txtVAL
Else
txtControl.text = txtVAL
End If
End If
End Sub
要在不同的线程中使用它,请调用
AddText(MyTextBoxObject, "add this text please, don't append", False)
作为参考,如果要访问UI控件的属性并获取其设置值,可以使用:
Private Delegate Function CheckedStatus_DL(ByVal checkable As Control) As Boolean
Function CheckedStatus(ByVal checkable As Control) As Boolean
If checkable.InvokeRequired = True Then
Dim gridDel As New CheckedStatus_DL(AddressOf CheckedStatus)
Dim parameters(0) As Object
parameters(0) = checkable
Return checkable.Invoke(gridDel, parameters)
Else
Return checkable.checked
End If
End Function
您还可以将此
函数
与任何具有属性的控件一起使用。选中的属性您可以在类上全局定义一个子类,如下所示:
Private Delegate Sub AddText_DL(ByVal txtControl As Control, ByVal txtVAL As String, ByVal append As Boolean)
Private Sub AddText(ByVal txtControl As Control, ByVal txtVAL As String, ByVal append As Boolean)
If txtControl.InvokeRequired = True Then
Dim progDel As New AddText_DL(AddressOf AddText)
Dim parameters(2) As Object
parameters(0) = txtControl
parameters(1) = txtVAL
parameters(2) = append
txtControl.Invoke(progDel, parameters)
Else
If append = True Then
txtControl.text &= txtVAL
Else
txtControl.text = txtVAL
End If
End If
End Sub
要在不同的线程中使用它,请调用
AddText(MyTextBoxObject, "add this text please, don't append", False)
作为参考,如果要访问UI控件的属性并获取其设置值,可以使用:
Private Delegate Function CheckedStatus_DL(ByVal checkable As Control) As Boolean
Function CheckedStatus(ByVal checkable As Control) As Boolean
If checkable.InvokeRequired = True Then
Dim gridDel As New CheckedStatus_DL(AddressOf CheckedStatus)
Dim parameters(0) As Object
parameters(0) = checkable
Return checkable.Invoke(gridDel, parameters)
Else
Return checkable.checked
End If
End Function
您还可以将此函数
用于任何具有属性的控件。选中的属性Form1.writeLog…
看起来像默认表单实例,但不能很好地处理线程。如果是这样,有更好的方法吗?是否正在创建控件CreateConrol()
在后台线程中?是的,但那是因为表单似乎没有句柄,即使它在Form1\u加载时有句柄。默认实例是特定于线程的。这意味着,如果您在UI线程上显示一个默认实例,然后在辅助线程上引用一个默认实例,那么实际上您引用的是另一个表单。您需要一个对首先显示的实际Form1
对象的引用,而不是在这种情况下使用默认实例。Form1.writeLog…
这看起来像默认表单实例,它与线程不兼容如果是这样,有更好的方法吗?您正在创建控件CreateConrol()
在后台线程中?是的,但那是因为表单似乎没有句柄,即使它在Form1\u加载时有句柄。默认实例是特定于线程的。这意味着,如果您在UI线程上显示一个默认实例,然后在辅助线程上引用一个默认实例,那么实际上您引用的是另一个表单。您需要一个对首先显示的实际Form1
对象的引用,而不是在这种情况下使用默认实例。不要鼓励延迟绑定。将控件prameter声明为ByVal txtControl为control
。这样,您还可以对传递给方法的内容施加限制。我必须设置对线程可用的表单的引用,以便您可以调用实例。DoSomething
,感谢大家的支持help@VisualVincent是的,我同意后期绑定,我编辑了它。感谢您指出这一点,不要鼓励延迟绑定。将控件prameter声明为ByVal txtControl为control
。这样,您还可以对传递给方法的内容施加限制。我必须设置对线程可用的表单的引用,以便您可以调用实例。DoSomething
,感谢大家的支持help@VisualVincent是的,我同意后期绑定,我编辑了它。谢谢你指出这一点