在运行时更新TextBox。跨线程操作无效

时间:2018-03-21 17:02:07

标签: vb.net tcp delegates thread-safety

我正在做一个TCP连接客户端/服务器,我真的想在运行时更新标签或文本框,因为我使用的是委托,它工作正常,但是当我尝试更新时Form1根本不能正常工作我喜欢。

在下面的代码中,我解释了我在做什么。

我有一个名为Form1的类:

Public Class Form1
Public server As tcp_server
Private Shared _instance As Form1 = Nothing

Public Shared ReadOnly Property MainInstance As Form1
    Get
        Return _instance
    End Get
End Property

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    If Form1._instance Is Nothing Then
        Form1._instance = Me 'Setting the main instance if none exists.
    End If

    server = New tcp_server("192.168.30.31", "5000")
    server.connect()

End Sub

Delegate Sub SetTextCallback(ByVal textBox As TextBox, ByVal text As String)

Public Sub SetText(ByVal textBox As TextBox, ByVal text As String)

    Try
        If textBox.InvokeRequired Then
            Dim d As SetTextCallback = New SetTextCallback(AddressOf SetText)
            Me.Invoke(d, New Object() {textBox, text})
        Else
            textBox.AppendText(text)


            'Me.ShowDialog()

            Form1.MainInstance.Visible = False
            Form1.MainInstance.ShowDialog()
        End If

    Catch ex As Exception

    End Try

End Sub

End Class

错误发生在Form1.MainInstance.ShowDialog()

Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.

其他类使用方法调用tcp_server

 Public Sub connect()
    Try
        Dim server_ipendpoint As New IPEndPoint(IPAddress.Parse(m_ip_host), m_port_host)
        tcpLsn = New TcpListener(server_ipendpoint)
        tcpLsn.Start()

        tcpThd = New Thread(AddressOf waiting_client)
        tcpThd.Start()
        'Form1.Label2.Text = "Listening"
        Form1.TextBox1.Text = "Listening" & vbCrLf

    Catch ex As Exception
        is_exception = True
    End Try

End Sub

在这种方法中,你可以看到我开始收听传入的连接。

新线程称为waiting_client

Private Sub waiting_client()
    Try
        Dim change_name_label As New Form1.SetTextCallback(AddressOf Form1.SetText)
        change_name_label.Invoke(Form1.TextBox1, "helllllooooooooo")

    Catch ex As Exception
    End Try
End Sub

我无法在运行时更新TextBox1。该应用程序不会刷新Windows窗体。

我唯一得到的就是这个,它正在做:

Public Sub SetText(ByVal textBox As TextBox, ByVal text As String)

    Try
        If textBox.InvokeRequired Then
            Dim d As SetTextCallback = New SetTextCallback(AddressOf SetText)
            Me.Invoke(d, New Object() {textBox, text})
        Else
            textBox.AppendText(text)
            Me.ShowDialog()
        End If

    Catch ex As Exception
    End Try
End Sub

enter image description here

但这不是真正想要的结果。

我想更新TextBox1,我的意思是更改Listening --> helllloooooo

我阅读了很多帖子,但找不到解决方案。

所有评论或想法我们将不胜感激。

感谢的。

1 个答案:

答案 0 :(得分:0)

我不知道为什么你到处都在调用ShowDialog(),但MainInstance属性的目的是用{{替换每个 Form1调用1}}。

特别是这条线导致错误:

Form1.MainInstance

因为它也需要改为:

change_name_label.Invoke(Form1.TextBox1, "helllllooooooooo")

此外,您不必真正创建上面使用的change_name_label.Invoke(Form1.MainInstance.TextBox1, "helllllooooooooo") 委托实例,您只需致电:

change_name_label

......这就足够了。 Form1.MainInstance.SetText(Form1.MainInstance.TextBox1, "helllllooooooooo") 方法已经为您完成剩下的工作。

现在,为了使您的代码正常工作,您需要做的最后一件事就是摆脱SetText()调用。您还应该删除ShowDialog()Try/Catch方法中的SetText(),因为在任何地方添加空的方法都是不好的做法。如果您要将waiting_client()置于可能发生错误的位置,则应通过记录或将其显示给用户(或两者)来正确处理。

<强> Form1中:

Try/Catch

(请注意,Private Delegate Sub SetTextCallback(ByVal textBox As TextBox, ByVal text As String) Public Sub SetText(ByVal textBox As TextBox, ByVal text As String) If textBox.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText) textBox.Invoke(d, New Object() {textBox, text}) Else textBox.AppendText(text) End If End Sub 可以缩短为Dim d As SetTextCallback = New SetTextCallback

<强> tcp_server:

Dim d As New SetTextCallback

现在你的代码应该正常工作了!