【问题标题】:VB.net trying to access a UI element from seperate thread is not workingVB.net 试图从单独的线程访问 UI 元素不起作用
【发布时间】:2017-12-07 21:21:56
【问题描述】:

我的主目录中有一个富文本框,我想从不同的线程中写入内容。我曾尝试使用调用来做到这一点,但我似乎无法让它工作。如果我尝试:

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 的值,它会返回 @987654324 @。我尝试调用写作的方法是这样的:

线程类 sn-p:

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

事件处理类 sn-p:

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

主窗体sn-p:

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

【问题讨论】:

  • Form1.writeLog... 看起来像一个默认的表单实例,不能很好地处理线程
  • 如果是这样,有更好的方法吗?
  • 您是否在后台线程中创建控件CreateConrol()
  • 是的,但那是因为表单似乎没有句柄,即使它在 Form1_Load 中时也有。
  • 默认实例是线程特定的。这意味着如果您在 UI 线程上显示默认实例,然后在辅助线程上引用默认实例,那么您实际上是在引用不同的表单。您需要引用您最初显示的实际 Form1 对象,而不是在这种情况下使用默认实例。

标签: vb.net multithreading


【解决方案1】:

您可以在您的类上全局定义一个 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

您还可以将此Function 与任何具有.Checked 属性的控件一起使用

【讨论】:

  • 不鼓励后期绑定。将控制参数声明为ByVal txtControl As Control。这样,您还可以对可以传递给该方法的内容施加限制。
  • 我必须设置对线程可用表单的引用,以便您可以致电instance.DoSomething,感谢大家的帮助
  • @VisualVincent true 我同意后期绑定,我对其进行了编辑。谢谢指出
猜你喜欢
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
  • 2011-01-27
  • 2012-05-14
相关资源
最近更新 更多