Louis van Tonder
Louis van Tonder

Reputation: 3700

Cross Thread invoke from class ? Confused - vb.net

maybe I am being stooped... but the fact is that I am a bit of a n00b concerning threading...

I am making use of a serial port in a class. I am raising an event from that class to my form calling the class. Event contains data received...

I wish to simply populate a textbox from the raised event.

Now I am not specifically creating a seperate thread, but I get the normal crossthreading error when trying to update my textbox on the UI, so my assumption is that the serial port and its internal methods probably creates its own threads...

Regardless, I am a bit confused as to how to properly implement an invoke, from my main form, pointing to the thread in the instantiated class...

I hope this makes sense...

Dim WithEvents tmpRS232 As New clsRS232

Private Sub but_txt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles but_txt.Click
    tmpRS232.Set_com_port("COM8", 38400)
    tmpRS232.Transmit_data(txt_tx.Text)
End Sub

Private Sub tmprs232_rx_data_returned(ByVal str_data As String) Handles tmpRS232.rx_data_returned
    txt_rx.Text = str_data 'Cross threading error
    MsgBox(str_data) 'Fires without errors
End Sub

Can someone please provide a code example based on this code?

thanks.

Upvotes: 0

Views: 7077

Answers (2)

Simon B
Simon B

Reputation: 127

Or simply...

Private Sub tmprs232_rx_data_returned(ByVal str_data As String) Handles tmpRS232.rx_data_returned
    If InvokeRequired Then
        Invoke(Sub()txt_rx.Text = str_data)
    Else
        txt_rx.Text = str_data
    End If
End Sub

Upvotes: 2

robowahoo
robowahoo

Reputation: 1269

You are correct, the issue here is that you are attempting to update a UI element from a non-UI thread (in this case the serial port handler). What you need to do is check if the InvokeRequired flag is set on the control that you are trying to access from the callback. If so that means that you need to marshall your call to the UI thread. You can achieve this by using either Invoke or BeginInvoke from System.Windows.Forms.Control.

Private Delegate Sub SetRxTextCallback(ByVal [text] As String)

Private Sub SetRxText(ByVal [text] As String)
    txt_rx.Text = [text]
End Sub

Private Sub tmprs232_rx_data_returned(ByVal str_data As String) Handles tmpRS232.rx_data_returned

    If (txt_rx.InvokeRequired) Then
        Dim d As New SetRxTextCallback(AddressOf Me.SetRxText)
        Me.BeginInvoke(d, New Object() {[str_data]})
    End If

    'txt_rx.Text = str_data 'Cross threading error
    'MsgBox(str_data) 'Fires without errors
End Sub

Here's a link to the MSDN documentation that explains it in detail.

Upvotes: 5

Related Questions