Vb.net 在运行时更新文本框。跨线程操作无效
我正在做一个TCP连接客户机/服务器,我真的想在运行时更新一个标签或文本框,因为我使用的是一个委托,它工作正常,但当我尝试更新Form1时,它根本不能像我所希望的那样工作 在下面的代码中,我解释了我在做什么 我有一个叫做Form1的课程: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
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()
。