Vb.NET, waiting for a character to arrive in the serial port

Discussion in 'Computing and Networks' started by cmartinez, Apr 30, 2016.

  1. cmartinez

    Thread Starter AAC Fanatic!

    Jan 17, 2007
    3,560
    2,529
    I've been programming in .NET for years now, and already know how to use background workers and on_comm events when working with serial ports.

    There is one thing, however, that I'm sure could be done far more efficiently and elegantly than the way I've been doing it until now. And that is, wait for a character to arrive at the serial port.
    To make a long story short, these are the couple of lines of code that I've been using to accomplish that.

    'wait until the controller sends a character to the serial port
    While SPort.BytesToRead < 1 : Threading.Thread.Sleep(300) : End While
    xx = SPort.ReadByte()

    Is there a better way to do this? I'm trying to avoid using the on_comm event for this purpose because doing so requires splitting the code in several segments.

    This is what I do not want to do:
    • Set up and activate the on_comm event
    • Once the event is triggered, remove its handler to prevent it from triggering aditional events if more characters arrive
    • Perform several not so easy to understand Invoke instructions from within the event handler so as to execute a procedure and change the state of the form's controls.
    • After this is done re-assign the event handler and exit the event handling routine.
    • Continue the program in a different routine

    Doing all of that is not only cumbersome, but also makes the code hard to follow. My technique, however, uses more CPU resources and makes the program run slower and the computer feel jumpy and glitchy.

    Is there a simpler, and more fluid way of doing this?
     
  2. wayneh

    Expert

    Sep 9, 2010
    12,100
    3,034
    Short answer: I can't help you.

    Longer answer: Maybe if I ramble for a minute you'll have an aha! moment.

    I've been programming an iPhone app in Swift and Xcode (the IDE). One of the most mysterious functions I've had to learn is how to pause, delay and, wait, and work in parallel. For instance some of the things I'm working on require starting a web session and scraping a piece of information from a website. I need my code to wait patiently for the data to arrive and then handle things ASAP once it does. Thanks to Google and the kindness of strangers, I've had some success with this but pretty much just by brute force and dumb luck.

    Probably the most useful technique I've learned is the Grand Central Dispatch. Rather than make you suffer a description from an idiot (me), I've found a fairly decent summary of the concept and how it works. Maybe if you skim it something will jump out, or you'll be able to see some parallel to your own dilemma.
     
    cmartinez likes this.
  3. hellifino

    New Member

    Jul 2, 2015
    19
    1
    I haven't messed with VB in awhile, but I can give you a few paths to search down.

    Typically there are 2 flavors of I/O reading: blocking and non-blocking. By using BytesToRead(), you're creating your own non-blocking read. I believe the default for most .NET read functions is blocking. The main issue with your loop is that you are always waiting 300ms for the next check. Of course this is trivial in user-related I/O but still.. Anyway you use blocking I/O calls when you want immediate interrupts and you're not doing any buffering etc.

    The proper way is to let the OS handle the interrupt for you (unless you want to write that yourself). Something similar to:
    while (SPort.Read(&buffer...) == 0){ } // note that read(...) should be blocking execution

    Or idk if this works:
    short data = -1
    do{
    try{
    data = SPort.ReadByte()
    } catch (...) {} // do nothing with the exception
    } while (data < 0);


    Looks like there's an msdn on this... looks pretty close. Using SerialPort.ReadLine()
    https://msdn.microsoft.com/en-us/library/7ya7y41k.aspx


    One last point I will mention - I'm not sure if there is a timeout on the serialport.read. There should be, but sometimes with .NET these can be ~30 seconds and is very annoying to wait for when you try to close things. If that's the case, I would dump your read/write into a dedicated thread and have the OS interrupt the thread when you want to break the timeout.
     
Loading...