UDP Data Capture Thread Issue

Hi All,

I am trying a new approach to my data capture/monitor project.  I have read up on a lot of vb.net UDP actions and methods and I have had some success.  However, I am now at a loss.  I have a server that listens on a thread for data that arrives and shows the sender ip:port and the text received.  This is derived from the code on this technotif page:
http://technotif.com/creating-simple-udp-server-client-transfer-data-using-c-vb-net/

With their example and a bit of tweaking as it was written before VS2017, I got both sender and receiver to work.  My next step was to break out of seeing both IP and text received in one box because I want to display them separately and use a traffic light if data is lost as the datastream will be 24H7.  The ultimate app goal is to handle what could be multiple UDP datagrams (up to 12 from outside my local network), all sources identified in a list box, capture the dat in hex and write to a file for 1 hour and then recapture and of course in parallel will be a window showing that all identified sources are still being received so if one is lost a label will turn from green to red.

The latest hurdle I can't seem to get over is that any of the lines after Line 18 line throws an invalidoperationexception and I can't figure out why.  All I have done is split the original concatenated text into two boxes and added a color change to the text box, which was working fine.

I have added snips of the exception and the thread menu item.

Appreciate any thoughts.

Regards,

Clay
[/code]
Imports System.Threading
Imports System.Net
Imports System.Net.Sockets
Imports System.Text

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim ThdUDPServer = New Thread(New ThreadStart(AddressOf ServerThread))
        ThdUDPServer.Start()
    End Sub

    Public Sub ServerThread()
        Dim UdpClient As New UdpClient(8080)
        While True
            Dim RemoteIpEndPoint As New IPEndPoint(IPAddress.Any, 0)
            Dim ReceiveBytes As Byte()
            ReceiveBytes = UdpClient.Receive(RemoteIpEndPoint)
            Dim ReturnData As String = Encoding.ASCII.GetString(ReceiveBytes)
            TxtDataRx.BackColor = Color.Green
            LbConnections.Items.Add(RemoteIpEndPoint.Address.ToString())
            TxtDataRx.Text = TxtDataRx.Text & vbCrLf & returnData.ToString()

        End While
    End Sub
End Class


[/code]
Formthread errorthread debug
LVL 2
Clay WillingEng Ops MgrAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Fernando SotoRetiredCommented:
Hi Clay;

According to the exception you are attempting to access a GUI control from a thread that did not create it, this is not allowed. The object ThdUDPServer is created in a new thread and the code in that thread is trying to change the control state. Please see this Microsoft web page to see how to get around this issue. How to: Make Thread-Safe Calls to Windows Forms Controls
0
Clay WillingEng Ops MgrAuthor Commented:
Fernando ,
I did look into this but I can't see why the code worked at first and then adding the extra line now means the thread is broken.
As far as I can see the list box works okay in isolation but I can't change the text box too.
If I focus on the unsafe thread, do you have any pointers on what to change the code to be safe?
0
Fernando SotoRetiredCommented:
Hi Clay;

In the link I posted read the section called "Making Thread-Safe Calls to Windows Forms Controls" it has sample code showing what is needed.
0
Become a Certified Penetration Testing Engineer

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

it_saigeDeveloperCommented:
As stated by Fernando, you are attempting to modify a control from a thread that did not create the control.

Two of the more common ways to handle this issue:

1.  Invoke the action onto the control; e.g. -
Imports System.ComponentModel
Imports System.Net
Imports System.Net.Sockets
Imports System.Runtime.CompilerServices
Imports System.Text
Imports System.Threading

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim ThdUDPServer = New Thread(New ThreadStart(AddressOf ServerThread))
        ThdUDPServer.Start()
    End Sub

    Public Sub ServerThread()
        Dim UdpClient As New UdpClient(8080)
        While True
            Dim RemoteIpEndPoint As New IPEndPoint(IPAddress.Any, 0)
            Dim ReceiveBytes As Byte()
            ReceiveBytes = UdpClient.Receive(RemoteIpEndPoint)
            Dim ReturnData As String = Encoding.ASCII.GetString(ReceiveBytes)
            TxtDataRx.HandleInvokeRequired(Sub(tb)
                                               tb.BackColor = Color.Green
                                               tb.Text = String.Format("{0}{1}{2}", tb.Text, Environment.NewLine, ReturnData.ToString())
                                           End Sub)
            LbConnections.HandleInvokeRequired(Sub(lb) lb.Items.Add(RemoteIpEndPoint.Address.ToString()))
        End While
    End Sub
End Class

Module Extensions
    <Extension()>
    Public Sub HandleInvokeRequired(Of T As {Control, ISynchronizeInvoke})(control As T, action As Action(Of T))
        'Check to see is the control is not null
        If control Is Nothing Then
            Throw New ArgumentNullException(String.Format("Cannot execute {0} on {1}.  {1} is null.", action, control))
        End If

        'Check to see if the control is disposed.
        If TypeOf control Is Control AndAlso TryCast(control, Control).IsDisposed Then
            Throw New ObjectDisposedException(String.Format("Cannot execute {0} on {1}.  {1} is disposed.", action, control))
        End If

        'Check to see if the handle is created for the control.
        If TypeOf control Is Control AndAlso Not TryCast(control, Control).IsHandleCreated Then
            Throw New InvalidOperationException(String.Format("Cannot execute {0} on {1}.  Handle is not created for {1}.", action, control))
        End If

        'Check to see if the control's InvokeRequired property is true
        If control.InvokeRequired Then
            Try
                'Use Invoke() to invoke your action
                Console.WriteLine("Invoking the action {0}; on {1}", action, control)
                control.Invoke(action, New Object() {control})
            Catch ex As Exception
                Throw New Exception(String.Format("Cannot execute {0} on {1}.  {2}.", action, control, ex.Message))
            End Try
        Else
            Try
                'Perform the action
                Console.WriteLine("Performing the action {0}; on {1}", action, control)
                action(control)
            Catch ex As Exception
                Throw New Exception(String.Format("Cannot execute {0} on {1}.  {2}.", action, control, ex.Message))
            End Try
        End If
    End Sub
End Module

Open in new window

2.  Use a backgroundworker; e.g. -
Imports System.ComponentModel
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Public Class Form1
    Private WithEvents worker As New BackgroundWorker() With {.WorkerReportsProgress = True, .WorkerSupportsCancellation = True}
    Private UdpClient As New UdpClient(8080)
    Private RemoteIpEndPoint As New IPEndPoint(IPAddress.Any, 0)
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        worker.RunWorkerAsync()
    End Sub

    Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        worker.CancelAsync()
    End Sub

    Private Sub worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles worker.DoWork
        If TypeOf sender Is BackgroundWorker Then
            Dim worker = DirectCast(sender, BackgroundWorker)
            While Not worker.CancellationPending
                Dim ReceiveBytes As Byte()
                ReceiveBytes = UdpClient.Receive(RemoteIpEndPoint)
                Dim ReturnData As String = Encoding.ASCII.GetString(ReceiveBytes)
                worker.ReportProgress(0, New Object() {RemoteIpEndPoint, ReturnData})
            End While
        End If
    End Sub

    Private Sub worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles worker.ProgressChanged
        Dim endpoint As IPEndPoint = DirectCast(e.UserState(0), IPEndPoint)
        Dim message As String = DirectCast(e.UserState(1), String)
        TxtDataRx.BackColor = Color.Green
        TxtDataRx.Text = String.Format("{0}{1}{2}", TxtDataRx.Text, Environment.NewLine, message)
        LbConnections.Items.Add(endpoint.Address.ToString())
    End Sub
End Class

Open in new window

Each of which produces the following output -Capture.PNG
-saige-
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Clay WillingEng Ops MgrAuthor Commented:
Fantastic. In that case I have a bit of work ahead of me to see how they both relate to the thread unsafe call note in msdn.
Appreciate the assistance
Next step will be to see how many instances the receiver can pick up and handle.
Also no error handling yet and no elegance exiting of the app.  Cleaning up was a big thing in charge for me but this is more a learning curve just now.
Thanks again
0
Clay WillingEng Ops MgrAuthor Commented:
As per last post thanks saige
0
Fernando SotoRetiredCommented:
Well you can't win them all.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.