Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 在运行时更新文本框。跨线程操作无效_Vb.net_Tcp_Delegates_Thread Safety - Fatal编程技术网

Vb.net 在运行时更新文本框。跨线程操作无效

Vb.net 在运行时更新文本框。跨线程操作无效,vb.net,tcp,delegates,thread-safety,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 MainIn

我正在做一个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()

跨线程操作无效:从创建控件“Form1”的线程以外的线程访问控件“Form1”。

和另一个名为
tcp\u 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\u 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

但这并不是我们真正想要的结果

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

我读了很多帖子,但找不到解决办法

所有意见或想法将不胜感激


谢谢。

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

具体来说,是这一行导致了错误:

change_name_label.Invoke(Form1.TextBox1, "helllllooooooooo")
因为它也需要更改为:

change_name_label.Invoke(Form1.MainInstance.TextBox1, "helllllooooooooo")
此外,您实际上不必创建上面使用的
change\u name\u标签
delegate实例,只需调用:

Form1.MainInstance.SetText(Form1.MainInstance.TextBox1, "helllllooooooooo")
…这就足够了。
SetText()
方法已经为您处理了其余部分

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

表格1:

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
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.MainInstance.TextBox1.Text = "Listening" & vbCrLf
    Catch ex As Exception
        is_exception = True
    End Try
End Sub

Private Sub waiting_client()
    Form1.MainInstance.SetText(Form1.MainInstance.TextBox1, "helllllooooooooo")
End Sub
(注意,
Dim d As SetTextCallback=New SetTextCallback
可以缩短为
Dim d As New SetTextCallback

tcp\u服务器:

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
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.MainInstance.TextBox1.Text = "Listening" & vbCrLf
    Catch ex As Exception
        is_exception = True
    End Try
End Sub

Private Sub waiting_client()
    Form1.MainInstance.SetText(Form1.MainInstance.TextBox1, "helllllooooooooo")
End Sub

现在你的代码应该可以工作了

无法通过默认实例从后台线程访问窗体。可能是重复的我已经读过这篇文章,但它对我没有任何帮助,我也试着做同样的事情,但不起作用。谢谢你的通讯网。它肯定会对你有所帮助。在我的回答中,我描述了导致代码按当前方式运行的确切现象,即您无法通过后台线程中的默认实例访问
Form1
(或任何其他形式)。你的问题真的没有别的答案了也请定义“不工作”。“默认实例”是指直接通过表单名称访问表单,而不必创建表单实例,例如
Dim newForm as New Form1
。VB.NET是唯一允许您通过
Form1
直接访问它的语言(即,您可以调用
Form1.Show()
而不是
myForm.Show()
),如果您不确切知道它们的行为,这实际上是一个相当大的问题。这里有太多的问题,根本原因是缺乏关于默认实例如何工作的知识(因为很难知道,特别是因为它没有很好的文档记录)。我已经尝试了你在那篇文章中所说的一切,但仍然是相同的错误,跨线程操作无效。。。。我无法在运行时更新TextBox,我发现的唯一方法是我在帖子中提到的。我是这类问题的初学者,没有找到其他解决办法。我将非常感谢任何帮助或解决这个问题的方法。谢谢。我做了这个更改,但是我忘记了
Dim change\u name\u标签为New Form1.SetTextCallback(AddressOf Form1.maincinstance.SetText)
。无论如何,你是对的,处理一个简单的电话要容易得多。最后一件事,我什么时候应该使用委托,因为我知道如何使用它,但不知道什么时候是使用它的最佳时机?谢谢,我真的很感谢你的帮助Vincent@CarlosZuazu:在这种情况下,您只需要在调用时使用委托。委托用于将方法视为常规对象(您可以调用其中的内容,将其放入变量,将其作为参数传递给其他方法,等等)。现在,您正在将要在UI线程上运行的方法作为参数传递给
Control.Invoke()