Invoke is hanging...

jared

Newcomer
Joined
Mar 28, 2003
Messages
2
Hi all! I am working on an app using VB.Net 2005 Express. I am receiving data from the serial port and simply updating a few labels with the data I receive. I am using MethodInvoker to invoke a method that simply reads the data from the serial port buffer and updates the values on a few labels.

If I am receiving data faster than I can update the UI (there is more data in the receive buffer to process) and try to close the application it hangs.

I'm guessing this is because the SerialPort component has fired a bunch of DataReceived events which created a long list of methods to invoke.

Here is my DataReceived event and Method that is called via the MethodInvoker...

Code:
Private Sub SerialPort1_DataReceived _
        (ByVal sender As Object, _
        ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
        Handles SerialPort1.DataReceived

        ' If we receive any character then...
        If e.EventType = IO.Ports.SerialData.Chars Then

            ' If we have received at least two bytes then
            ' Create a MethodInvoker and call ProcessData
            Dim MI As MethodInvoker
            MI = New MethodInvoker(AddressOf ProcessData)
            Invoke(MI)

        End If

    End Sub


   Private Sub ProcessData()
        ' Crate a place to store the two bytes
        Dim Data(1) As Byte

        ' Create a place to store the 16 bit result
        Dim Result As Integer


        ' Read the first two bytes in the buffer
        ' into our array named Data
        SerialPort1.Read(Data, 0, 2)

        ' Combine the bytes to create a 16 bit word value
        Result = CInt((Data(0) * &H100&) Or Data(1))

        ' Display the result
        lblPressure.Text = "Pressure Value = " & Result.ToString

        If Result > 60000 Then
            lblAlarm.Text = "Pressure to high!"
            lblAlarm.ForeColor = Color.Red
        ElseIf Result >= 10000 Then
            lblAlarm.Text = "Pressure normal."
            lblAlarm.ForeColor = Color.Black
        Else
            lblAlarm.Text = "Pressure too low!"
            lblAlarm.ForeColor = Color.Blue
        End If

    End Sub

End Class

I have tried commenting out all of the code in the ProcessData sub and the problem still occurs.

I have removed the MethodInvoker code and simply displayed the data to the debug window from the DataReceived event and there is no problem.

The problem is definitely related to the cross thread call.

I found one workaround, but it is not predictable...

If I add a Application.DoEvents in the Form_Closing event sometimes the application will shut down correctly. I think it matters how many events are in the message que though. Sometimes it may take two or three Application.DoEvents to successfuly allow the application to close. Just matters how long I let the app run before I try to close it.

Any idea of how to fix this problem?

Thanks,

Jared
 
What you want to do is call the Form.Invoke method on the Form that you want to update. The Form.Invoke method ensures that the method being invoked is processed on the application's main thread.

Code:
[Color=Blue]Private Sub[/Color] SerialPort1_DataReceived _
    ([Color=Blue]ByVal [/Color]sender [Color=Blue]As [/Color]Object, _
    [Color=Blue]ByVal [/Color]e [Color=Blue]As [/Color]System.IO.Ports.SerialDataReceivedEventArgs) _
    [Color=Blue]Handles [/Color]SerialPort1.DataReceived
 
    [Color=Green]' If we receive any character then...
[/Color]    [Color=Blue]If [/Color]e.EventType = IO.Ports.SerialData.Chars [Color=Blue]Then[/Color]
        SomeFormThatContainsLabels.Invoke( _
            [Color=Blue][Color=Blue]AddressOf [/Color][/Color]ProcessData)
[Color=Blue]    End If
End Sub[/Color]
Haven't tested that, but it should at least give you an idea.
 
Back
Top