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