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是的,我同意后期绑定,我编辑了它。谢谢你指出这一点