Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing Delegates to Pass Information back to UI from custom socket class
    text
    copied!<p>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.</p> <p>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.</p> <p>Below is a code excerpt from the protoype app which should put the above into appropriate context:</p> <p><strong>Code from the form:</strong></p> <pre><code>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></pre> <p><strong>Code from TCPDevice Class</strong> </p> <pre><code>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 " &amp; vbCrLf &amp; " .") 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 " &amp; vbCrLf &amp; " ." &amp; _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 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload