使用委托将信息从自定义套接字类传递回UI

时间:2010-10-06 12:00:52

标签: vb.net sockets delegates tcplistener

基本上,我有一个服务器应用程序和相关的代理程序进程,用于将心跳数据传送到服务器。服务器应用程序实现TCP套接字类(TCPDevice),该类从WinForm调用。我知道从在不同线程上运行的进程更新UI的限制,并且实现这一点的首选技术是通过将Delegates与Invoke方法结合使用。以前很少需要使用Delegates(当然除了std windows事件和BackGroundWorker控件),我在如何在我的应用程序的上下文中做这件事感到茫然,并且会感谢一些帮助,尽管它有我发现我可以使用backgroundworker来编组UI的更新。

最终,应用程序需要通过来自已定义代理的提要更新设备网格,但是为了本练习的目的,只需更新UI上的状态栏就足够了。我认为与代码传播到表单相关的代码部分包含在OnDataReceived方法中。

以下是protoype应用程序的代码摘录,该应用程序应将上述内容放入适当的上下文中:

表单中的代码:

Private _device As TcpDevice

Private Sub btnListen_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnListen.Click
        _device = New TcpDevice(uxIPaddress.Text, uxHost.Text, CInt(uxPort.Text))
        _device.Listen()
        Me.btnListen.Enabled = False
End Sub

来自TCPDevice类的代码

Public Class TcpDevice : Implements CNIMonitor.Core.Domain.IDevice

    Private _ipAddress As String
    Private _hostName As String
    Private _port As Integer
    Private _status As Integer
    Private _previousStatus As Integer
    Private _listener As TcpListener
    Private _localAdd As System.Net.IPAddress


    Private _activeConnection As TcpClient
    Private _receiveBuffer(0) As Byte
    Private _sendBuffer As Byte
    Private _message As String
    Private _dataRead As Integer 'The value returned from the getstream.endread method


    Public Sub New(ByVal ipAddress As String, ByVal HostName As String, ByVal port As String)
        _ipAddress = ipAddress
        _hostName = HostName
        _port = port
    End Sub

    Public Sub Connect() Implements CNIMonitor.Core.Domain.IDevice.Connect

    End Sub

    Public Sub Disconnect() Implements CNIMonitor.Core.Domain.IDevice.Disconnect

        _activeConnection.Close()
        _listener.Stop()

        _activeConnection = Nothing

    End Sub

    Public Property HostName() As String Implements CNIMonitor.Core.Domain.IDevice.HostName
        Get
            HostName = _hostName
        End Get
        Set(ByVal value As String)
            _hostName = value
        End Set
    End Property

    Public Property IPAddress() As String Implements CNIMonitor.Core.Domain.IDevice.IPAddress
        Get
            IPAddress = _ipAddress
        End Get
        Set(ByVal value As String)
            _ipAddress = value
        End Set
    End Property

    Public Sub Listen() Implements CNIMonitor.Core.Domain.IDevice.Listen
        Try
            'Server component listens on the specified tcpip port
            _localAdd = System.Net.IPAddress.Parse(_ipAddress)
            _listener = New TcpListener(_localAdd, _port)
            _listener.Start()
            _listener.BeginAcceptTcpClient(AddressOf OnClientConnect, _listener)
            'Update the status message                
            Debug.WriteLine("Listening for host " + _ipAddress + " on port " + _port.ToString + ".")
        Catch ex As SocketException
            Debug.WriteLine("Failed listening on " + _ipAddress + " over port " & vbCrLf & " .")
        End Try
    End Sub

    Private Sub OnClientConnect(ByVal ar As IAsyncResult)

        Debug.WriteLine("Received connection from " + ar.AsyncState.ToString)
        'Get the connection object                
        _activeConnection = _listener.EndAcceptTcpClient(ar)
        'on Client connect                
        Debug.WriteLine("Client" + _ipAddress + " connected over port " & vbCrLf & " ." & _port.ToString)
        'Bind the event handler for dealing with incoming data                
        _activeConnection.GetStream.BeginRead(_receiveBuffer, 0, _receiveBuffer.Length, AddressOf onDataReceived, _
            Nothing)
    End Sub

    Private Sub onDataReceived(ByVal ar As IAsyncResult)
        Dim receiveLength As Integer = 0
        ReDim _receiveBuffer(_activeConnection.ReceiveBufferSize - 1)
        Try
            Debug.WriteLine("Receiving from " + _ipAddress + ".")
            ' Complete the BeginReceive() asynchronous call by EndReceive() method                
            ' which will return the number of bytes written to the stream                 
            ' by the client                
            receiveLength = _activeConnection.GetStream.EndRead(ar)
            _message = Encoding.ASCII.GetString(_receiveBuffer, 0, receiveLength)
            _activeConnection.GetStream.BeginRead(_receiveBuffer, 0, _receiveBuffer.Length, AddressOf onDataReceived, Nothing)

            'NOW PASS THE INFORMATION RECEIVED BACK TO THE FORM

        Catch
            Debug.WriteLine("Transmission complete")
        End Try
    End Sub



    Public Property Port() As Integer Implements CNIMonitor.Core.Domain.IDevice.Port
        Get
            Port = _port
        End Get
        Set(ByVal value As Integer)
            _port = value
        End Set
    End Property

    Public Property PreviousStatus() As Integer Implements CNIMonitor.Core.Domain.IDevice.PreviousStatus
        Get
            PreviousStatus = _previousStatus
        End Get
        Set(ByVal value As Integer)
            _previousStatus = value
        End Set
    End Property

    Public Property Status() As Integer Implements CNIMonitor.Core.Domain.IDevice.Status
        Get
            Status = _status
        End Get
        Set(ByVal value As Integer)
            _status = value
        End Set
    End Property


End Class

1 个答案:

答案 0 :(得分:0)

进行了一些进一步的调查,设法使代码工作。