Click here to Skip to main content
15,879,535 members
Please Sign up or sign in to vote.
1.80/5 (2 votes)
See more:
Hi All,
I am using the code below that reads 2 temperature streams from the serial port.
The code seems a little bit unreliable and locks when trying to close. It hangs on the
VB
Dim str2 As String = sp.ReadLine


I have slowed the speed of the incoming two streams and that seems to cure the problem. Unfortunately its to slow for the operation I require.

Is there and way I can sort the problem?

Thank you in advance Nevjc



VB
Imports System.Drawing.Drawing2D
Imports System.IO.Ports

Public Class Form1
    Dim bmp1 As Bitmap = New Bitmap(165, 550)
    Dim temperature1 As Double = 10
    Dim temperature2 As Double = 10
    Dim WithEvents sp As New SerialPort

    Private Sub pictherm1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles pictherm1.Paint
        Dim g As Graphics = e.Graphics
        g.Clear(Color.White)
        ' fill temperature1
        If temperature1 > 100 Then temperature1 = 100
        g.FillRectangle(Brushes.Green, 48, 525 - CInt(temperature1 * 5), 10, CInt(temperature1 * 5))
        ' fill temperature2
        If temperature2 > 100 Then temperature2 = 100
        g.FillRectangle(Brushes.Green, 108, 525 - CInt(temperature2 * 5), 10, CInt(temperature2 * 5))
        'draw scale
        g.DrawLine(Pens.Black, 60, 525, 60, 25)
        g.DrawLine(Pens.Black, 105, 525, 105, 25)
        ' minor ticks
        For i As Integer = 25 To 525 Step 5
            g.DrawLine(Pens.Black, 50, i, 60, i)
            g.DrawLine(Pens.Black, 105, i, 115, i)
        Next
        'major ticks
        Dim f As Font = New Font("Verdana", 10, FontStyle.Regular)
        Dim scale As Integer
        For i As Integer = 525 To 25 Step -25
            g.DrawLine(Pens.Black, 45, i, 60, i)
            g.DrawLine(Pens.Black, 105, i, 120, i)
            scale = (525 - i) / 5
            g.DrawString(Str(scale), f, Brushes.Black, 65, i - 8)
        Next
    End Sub

    Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
        Try
            sp.BaudRate = "9600"
            sp.PortName = "COM5"
            sp.Open()
            If sp.IsOpen Then
                btnConnect.Visible = False
                btnDisconnect.Visible = True
            End If
        Catch
            sp.Close()
        End Try
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
        If sp.IsOpen() Then
            MessageBox.Show("Press Hold Before Closing")
            e.Cancel = True
        End If
    End Sub

    Delegate Sub myMethodDelegate1(ByVal [text] As String)
    Dim myDelegate1 As New myMethodDelegate1(AddressOf ProcessReading1)

    Private Sub SerialPort_DataReceived1(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles sp.DataReceived
        Dim str1 As String = sp.ReadLine
        Dim firststr As String = Mid(str1, 1, 4)
        BeginInvoke(myDelegate1, firststr)
    End Sub

    Sub ProcessReading1(ByVal input As String)
        If IsNumeric(input) Then
            temperature1 = CDbl(input)
            lblLeft.Text = CDbl(temperature1)
            pictherm1.Refresh()
        End If
    End Sub

    Delegate Sub myMethodDelegate2(ByVal [text] As String)
    Dim myDelegate2 As New myMethodDelegate2(AddressOf ProcessReading2)

    Private Sub SerialPort_DataReceived2(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles sp.DataReceived
        Dim str2 As String = sp.ReadLine
        Dim secondstr As String = Mid(str2, 6, 5)
        BeginInvoke(myDelegate2, secondstr)

    End Sub

    Sub ProcessReading2(ByVal input As String)
        If IsNumeric(input) Then
            temperature2 = CDbl(input)
            lblRight.Text = CDbl(temperature2)
            lblTotal.Text = CDbl(temperature1 + temperature2)
            lblDiff.Text = CDbl(temperature1 - temperature2)
            pictherm1.Refresh()
        End If
    End Sub

    Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
        Try
            sp.Close()
            btnConnect.Visible = True
            btnDisconnect.Visible = False
            Exit Sub
        Catch
            MessageBox.Show("Some kind of problem.")
        End Try
    End Sub

End Class
Posted
Comments
[no name] 16-Apr-14 5:52am    
You wrote "......and locks when trying to close." Do you mean it hangs while closing the serial port? Because that is a very well known problem in .NET.
Member 10701701 16-Apr-14 6:44am    
Hi idle63. Yes you are correct it hangs while closing the serial port. It yellows out str2 As String = sp.Readline. It does work about 10% of the time unless I slow down the Data Rate coming in to the serial port and then the percentage of reliablility goes up.
Does that help? Nevjc
[no name] 16-Apr-14 6:58am    
I don't remember our workaround for this at the moment, but I will search for it. Meanwhile google ".net serialport close hangs". e.g. http://social.msdn.microsoft.com/forums/en-US/ce8ce1a3-64ed-4f26-b9ad-e2ff1d3be0a5/serial-port-hangs-whilst-closing.

It is very old I'm not sure whehter it has never been fixed. But I remember a colouge of min with recently shoutet about this mistake...I come back as soon I have concrete information. Regards, Bruno
Member 10701701 16-Apr-14 9:34am    
Thanks for the info Nevjc

Solving any synchronization problem by slowing anything down is not a solution at all; it only makes things worse To understand it, start here: http://en.wikipedia.org/wiki/Race_condition[^].

Manipulating timing, you can change the probability of something bad to happen, such as the deadlock: http://en.wikipedia.org/wiki/Deadlock[^].

If you make the probability of bad thing considerably low, this is the worst case: you don't solve the problem but hide it, and the final output is the most dangerous: the bad thing will happen not during testing at your company, but at the site of your customer, after prolonged use in real production, where it cause the most harm.

You probably can get further advice if you describe your goals and requirements in detail.

—SA
 
Share this answer
 
Comments
Member 10701701 16-Apr-14 5:03am    
Thanks for the links Sergey. At this stage this is a very basic prototype I am working on and I am trying to get it to a reasonable point that my friend can run it as proof of concept. If that is sucessful then i would need the code written professionally buy someone like your self. I started the project in the analog domain and only recently decided to use computor to read results and I have just got hooked into trying to get it to work but the code is to complicated for me. I am happy with the operation at the moment it would be nice just to sort a couple of the niggles out. Thanks again Nevjc
Sergey Alexandrovich Kryukov 16-Apr-14 9:20am    
"Buy someone"? Watch your language, please.
—SA
Member 10701701 16-Apr-14 10:39am    
should have been by
You Handle sp.DataReceived 2 Times.

the first time it gets handled in SerialPort_DataReceived1
you read the Data with
VB
Dim str1 As String = sp.ReadLine


so when se second Event SerialPort_DataReceived2 gets called right after that the
VB
Dim str2 As String = sp.ReadLine

can't read anything, as you have allready read the buffer in the previous Event.


I suggest you use only one Event to handle that.
And check that you allready have enough Data from the device.. like are there allready 20bytes or whatever your Hardware sends to you. (looks like 1 line with 2 tempvalues)

And Mid() is old.. better use str1.Substring() ;)
 
Share this answer
 
Comments
Member 10701701 16-Apr-14 5:08am    
Thank you F.Xaver. The original software only had one temperature display with one readline and it still hung with the speed of the stream. I added the second read and I originally tried the substring code but it wouldnt work. The mid routine was the only one that did.
I will give it another try.
Thanks for the help Nevjc
F. Xaver 16-Apr-14 5:55am    
Dim t As String = "test"
Debug.Print("Message1: {0}", Mid(t, 5))
Debug.Print("Message2: {0}", t.Substring(5))

that's because Mid will return "" here.. and Substring Throws an ArgumentOutOfRangeException, because you try to access parts of the String, which aren't there.

You need to check if the full message of the hardware is allready received. There could only be a "2" from "22.7" in the buffer when sp.DataReceived fires.
Member 10701701 16-Apr-14 6:47am    
Thanks for that I will give it a try
Nevjc

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900