2011-11-23 24 views
0

我試圖編寫一個小的異步套接字庫,我可以用它來創建客戶端/服務器應用程序。如果我將它放在表單中,我可以讓所有的代碼運行良好,但是如果我嘗試將它移出到它自己的類中,我無法弄清楚如何使用連接狀態更新表單等。下面是代碼,縮短了一點,以便更容易閱讀和輸入。異步套接字庫不更新形式

表格代號:

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 

NetworkModule類:

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 

有其實更多的那類,但是第一個消息出去後,我從來沒有得到任何東西。我不確定該從哪裏出發。我嘗試了很多我在谷歌搜索中找到的不同方法,其中一些來自這裏,一些不是。任何人有任何想法?

回答

1

這是我會怎麼把它改寫:

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 

NetworkModule類(部分):

Class NetworkModule 
    Public Delegate Sub NotifyDelegate(Msg as String) 

    Private Sub Notify(Msg as String) 
     If m_Form.InvokeRequired Then 
      m_Form.Invoke(Form1.NotifyDelegate, Msg) 
     Else 
      m_Form.Notify(Msg) 
     End If 
    End Sub 'Notify 

    Private mSocket as Socket 

    Private m_Form As Form1 

    Public Sub New(IP as string, Port as Integer, oForm As Form1) 
     m_Form = oForm 
     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 

更新與接口方法

不是通過形式本身是一個更好的機制實現一個接口。爲此,首先創建接口定義(請注意,爲方便起見,代理已移至接口):

Public Interface INotify 
    Sub Notify(Msg As String) 
    Delegate Sub NotifyDelegate(Msg As String) 
End Interface 

然後在窗體中實現接口。請注意表單現在決定是否需要Invoke。這允許INotify接口用於非UI場景,例如記錄到磁盤或事件日誌。

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 

最後,存儲到inotify的接口,而不是在NetworkModule形式引用(注意NetworkModule不再需要知道或關心的調用可能需要):

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 
+0

好吧,這實現會給我一個InvalidOperationException錯誤,並說在創建窗口句柄之前,Invoke或BeginInvoke無法在控件上調用。從我讀過的內容來看,如果句柄沒有創建,'InvokeRequired'將永遠是錯誤的,所以我甚至沒有嘗試修改它,似乎毫無意義。有什麼想法嗎? – Timbermar

+0

我嘗試將'NotifyDelegate = New NetworkMod ...'行從'New()'移動到'Form_Load()',相同的結果與相同的錯誤消息。將Form1.Invoke(...'行改爲'Form1.txtLog.Invoke(...') – Timbermar

+0

我假設你有一個全局變量掛在某處指向Form1的地方,但這可能沒有我已經通過修改代碼糾正了這個假設,以便調用形式在構造函數中傳遞給NetworkModule並作爲模塊級成員存儲在NetworkModule中。實際上,不應該傳遞表單類型;接口應該被創建並通過,但是你需要在清理之前獲得基本實現的功能 –