All
I am in the process of prototyping a small sockets application, which monitors IT infrastructure (due to in-house financial and deployment restrictions, I am unable to utilise an existing commercial or open-source solution). Basically, I have a server application and associated agent process for communicating heart-beat data to the server. The server application implements a TCP socket class (TCPDevice), which is called from a WinForm. I am aware of the restriction on updating the UI from processes running on separate threads, and that the preferred technique for acheiving this is via the use of Delegates in conjunction with the Invoke method. Having had very little need previously for using Delegates (apart from of course std windows events and the BackGroundWorker control), I am at a loss as to how to do this in the context of my application, and would appreciate some assistance, although it has occurred to me that I could use the backgroundworker for marshalling updates to the UI.
Eventually the application will need to update a grid of devices via feeds from the defined agents, however for the purpose of this exercise simply updating a status bar on the UI will suffice. The section of the code which I believe is relevant to propogating the code to the form is contained in the OnDataReceived method.
Below is a code excerpt from the protoype app which should put the above into appropriate context:
Code from the form:
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
Code from TCPDevice Class
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