Reading serial port in background and responding when needed

Sprint

Well-known member
Joined
Feb 3, 2006
Messages
58
Location
Ohio
Programming Experience
5-10
I have a app that needs to listen to a serial port and react when something happens. I have NOT yet figured out the hardware side of the serial port but it will be as simple as possible as all it needs to do is detect either a button pressed twice within one second or a constantly held button for two or more seconds (if anyone has an idea please let me know).

For now I just want to be able to read the serial port in the background without interfering with my app. What is the least resource intensive way of doing this? I was thinking something like this to start with:

VB.NET:
Private mySerialPortListenerThread As New Threading.Thread(AddressOf SeriaPortListener)

Private Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If My.Settings.SerialPortSenders.Contains(UCase(myCurrentUserName))
     mySerialPortListenerThread.IsBackground = True
     mySerialPortListenerThread.Start()
End If
End Sub

Private Sub SeriaPortListener()
' Do stuff for reading serial port here.  Something like:
End Sub

So this should start it on a background thread but I'm not sure how to go about the constant monitoring of the serial port. I also don't really want to add the "SerialPort" component because as you can see above I only want to enable this functionality for a very few select users. Or would it be better to "create" a SerialPort" component for the selected users and then use the DataReceived event?

I mainly want 0 resource impact on the users not in the allowed list and the lowest resource use possible for those that will have the serial port being used.
 
IMHO I would :-

1. Code the SerialPort manually, rather than use a form-based component. Declare it in a Module, so that it is form independent. That way, Serial Port communication is not limited by users having restricted form access. Open the Serial Port whenever you need to.

2. Use the MyApplication_Shutdown event for closing the Serial Port, as well as closing the port in MyApplication_UnhandledException.

3. Use the DataReceived event as you described. Free up the thread as soon as possible after receiving the data, by adding the data to a queue. Use another, totally separate thread, to process the received queue. Set the Thread Priority as appropriate.

4. Use Delegates wherever possible during testing to see when data is received !!
 
Last edited:
The serial port will only be accessed form the main form so creating it there isn't really a big deal. I guess here's a question....if I use the component for simplicity and just "open" the port for the selected users then it shouldn't affect the other users nor mess with there comm port correct?
 
Correct :)

My only reason for suggesting keeping the component away from the forms is based on prior experience. I created a multi-formed program with two Serial Port components, and when I modified the code to include different user access levels, the previous design problems started to become obvious .....
 
Great...thanks for your help. I'll add the component to my form, open it for just the users that should have access to it, and add a "If MainRibbonForm.SerialPort.IsOpen then MainRibbonForm.SerialPort.Close" to my shutdown and unhandled exception routines.

I'll most likely do something in the "PinChanged" event and short out pins to do what I want since I'm not really sending "data" but just trying to get a simple external signal into the program. Or buy something like this: PC digital inputs and outputs using a simple USB adaptor board and use there DLL to detect a button press. Either I suppose will work with shorting pins of course being the easiest way.
 
Ok...rewrote it with the SerialPort component and wanted to post it here so people can review to tell me if this makes sense and also to share. It seems to work how I want....just not sure if it's the right way of going about it:

(with a SerialPort added to my MainForm called SerialPortOnMainRibbonForm)

VB.NET:
Private mySerialPortEventIsHandled As Boolean = False
               
Private Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 ' Start up the Serial Port listener for hardware entry only for the predefined users
     If My.Settings.PanicAlertSerialPortSenders.Contains(UCase(myCurrentUserName)) Then
          SerialPortOnMainRibbonForm.Open()
     End If
End Sub

Private Sub SerialPort_PinChanged(sender As Object, e As System.IO.Ports.SerialPinChangedEventArgs) Handles SerialPortOnMainRibbonForm.PinChanged
     If e.EventType = Ports.SerialPinChange.CDChanged And mySerialPortEventIsHandled = False Then
          mySerialPortEventIsHandled = True
          Dim myTimerThread As New Thread(AddressOf MessageBoxForCDHolding)
          myTimerThread.IsBackground = True
          myTimerThread.Start()
     End If
End Sub

Private Sub MessageBoxForCDHolding()
     Dim x As Integer
     Do While x < 20
          If SerialPortOnMainRibbonForm.CDHolding = True Then
               Thread.Sleep(100)
               x += 1
          Else
               Exit Do
          End If
     Loop
     If x > 19 Then MsgBox("CDHolding was held in for 2 seconds")
     mySerialPortEventIsHandled = False
End Sub

-Allan
 
Back
Top