Vb.net 异步套接字库未更新表单
我试图编写一个小型异步套接字库,用于创建客户机/服务器应用程序。如果我把它留在表单中,我可以让所有代码正常运行,但是如果我试图将它移出到它自己的类中,我就不知道如何用连接状态更新表单,诸如此类的事情。下面是代码,略为缩短,以便于阅读和键入 表格编号:Vb.net 异步套接字库未更新表单,vb.net,asyncsocket,Vb.net,Asyncsocket,我试图编写一个小型异步套接字库,用于创建客户机/服务器应用程序。如果我把它留在表单中,我可以让所有代码正常运行,但是如果我试图将它移出到它自己的类中,我就不知道如何用连接状态更新表单,诸如此类的事情。下面是代码,略为缩短,以便于阅读和键入 表格编号: Class Form1 Dim Network as NetworkModule Public Sub Button1_Click(Sender, e) Handles Button1.Click Network = New Networ
Class Form1
Dim Network as NetworkModule
Public Sub Button1_Click(Sender, e) Handles Button1.Click
Network = New NetworkModule("127.0.0.1", 1234)
End Sub
End Class 'Form1
网络模块类:
Class NetworkModule
Private mSocket as Socket
Public Sub New(IP as string, Port as Integer)
Dim remoteEP as New IPEndpoint(IP.Parse(IP), Port)
mSocket = New Socket(internetwork, stream, tcp)
mSocket.BeginConnect(remoteEP, New AsyncCallback(AddressOf onConnect), mSocket)
Notify("Connection to " & remoteEP.ToString) 'This one works
End Sub 'New
Private Sub onConnect(ar as IAsyncResult)
mSocket = CType(ar.AsyncState, Socket)
mSocket.EndConnect(ar)
Notify("Connected") 'This one never shows
End Sub 'onConnect
Private Delegate Sub _Notify(Msg as String)
Private Sub Notify(Msg as String)
If Form1.txtLog.InvokeRequired Then
Form1.txtLog.Invoke(New _Notify(AddressOf Notify), Msg)
Exit Sub
End if
Form1.txtLog.Text &= Msg & vbcrlf
End Sub 'Notify
End Class 'NetworkModule
实际上,这门课还有很多内容,但在第一条消息发出后,我什么也没得到。我不知道接下来该怎么办。我在谷歌搜索中找到了很多不同的方法,有些是从这里找到的,有些不是。有人有什么想法吗?以下是我将如何重写它:
Class Form1
Private Network as NetworkModule
Public NotifyDelegate As NetworkModule.NotifyDelegate
Public Sub New()
NotifyDelegate = New NetworkModule.NotifyDelegate(AddressOf Notify)
End Sub
Public Sub Button1_Click(Sender, e) Handles Button1.Click
Network = New NetworkModule("127.0.0.1", 1234, Me)
End Sub
Public Sub Notify(Msg As String)
txtLog.Text &= Msg & vbCrLf
End Sub
End Class 'Form1
网络模块类(部分):
使用接口方法更新
比传递表单本身更好的机制是实现接口。为此,首先创建接口定义(请注意,为了方便起见,代理已移动到接口):
然后在表单中实现接口。注意,表单现在决定是否需要调用。这允许在非UI场景中使用INotify接口,例如记录到磁盘或事件日志
Public Class Form1
Implements INotify
Public Sub Notify(Msg As String)
txtLog.Text &= Msg & vbCrLf
End Sub
Private Sub INotify_Notify(Msg As String) Implements INotify.Notify
If Me.InvokeRequired Then
Me.Invoke(New INotify.NotifyDelegate(AddressOf Notify), Msg)
Else
Me.Notify(Msg)
End If
End Sub 'Notify
Private Network As NetworkModule
Public Sub Button1_Click(Sender, e) Handles Button1.Click
Network = New NetworkModule("127.0.0.1", 1234, Me)
End Sub
End Class 'Form1
最后,在NetworkModule中存储对INotify接口的引用,而不是表单(注意,NetworkModule不再需要知道或关心可能需要调用):
好的,这个实现给了我一个InvalidOperationException错误,表示在创建窗口句柄之前不能对控件调用Invoke或BeginInvoke。据我所知,如果没有创建句柄,
InvokeRequired
将始终为false,因此我甚至没有尝试修改它,似乎毫无意义。有什么想法吗?我尝试将NotifyDelegate=New NetworkMod…
行从New()
移动到Form\u Load()
,结果相同,错误消息相同。将Form1.Invoke(…
行更改为'Form1.txtLog.Invoke'时也是如此(…”。我假设您有一个指向Form1的全局变量挂在某处,但情况可能并非如此。我已通过修改代码纠正了这一假设,以便调用表单在构造函数中传递给NetworkModule,并作为模块级成员存储在NetworkModule中。实际上,表单类型应该没有被传递;应该创建并传递一个接口,但是在清理它之前,您需要使基本实现功能正常。这非常有效。如果您可以发布一个好的资源,这样我就可以继续使用该接口,那就太好了。我将把这标记为答案,如果我对该方法有任何问题,那么你已经建议,我将发布另一个问题。谢谢。@Timbermar:我已经更新了答案,说明了我将如何实现接口。
Public Interface INotify
Sub Notify(Msg As String)
Delegate Sub NotifyDelegate(Msg As String)
End Interface
Public Class Form1
Implements INotify
Public Sub Notify(Msg As String)
txtLog.Text &= Msg & vbCrLf
End Sub
Private Sub INotify_Notify(Msg As String) Implements INotify.Notify
If Me.InvokeRequired Then
Me.Invoke(New INotify.NotifyDelegate(AddressOf Notify), Msg)
Else
Me.Notify(Msg)
End If
End Sub 'Notify
Private Network As NetworkModule
Public Sub Button1_Click(Sender, e) Handles Button1.Click
Network = New NetworkModule("127.0.0.1", 1234, Me)
End Sub
End Class 'Form1
Public Class NetworkModule
Public Delegate Sub NotifyDelegate(Msg As String)
Private m_Notifier As INotify
Private Sub Notify(Msg As String)
m_Notifier.Notify(Msg)
End Sub 'Notify
Public Sub New(IP As String, Port As Integer, oNotifier As INotify)
m_Notifier = oNotifier
' The addition code here
End Sub 'New
End Class