locked
C# SerialPort receive buffer & input buffer RRS feed

  • Question

  •  

    I set the serialport  ReceivedBytesThreshold=320;

    when the program run into the DataReceived Event  ,the BytesToRead is only 140

     

    I knewsetting the  ReceivedBytesThreshold=320 means ,when the serial port received 320 bytes,it will trigger the DataReceived Event ,and the bytes in the receive buffer should be 320, but now it isn't.

     

    I noticed

    the BytesToRead is  :  Gets the number of bytes of data in the receive buffer.

    the ReceivedBytesThreshold is: Gets or sets the number of bytes in the internal input buffer before a DataReceived event occurs.

     

    so I confused that what is the difference between the the receive buffer and the internal input buffer ?

    Thursday, April 17, 2008 3:25 AM

Answers

  • nobugz

     

    I don't think you are correct here. The two chapters in my totorial have been written on the basis of information I have got directly from Kim Hamilton - the one, who has programmed SerialPort. Have you actually read the two chapters? If not, please do.

     

    There is a mutual blocking (lock) between all event handlers (and close), which prevents more eventhandlers from running at the same time. Therefore a new handler for the DataReceived event will not run or be scheduled before the last one is terminated and the thread pool thread returned to the pool. When a DataReceived event occur, SerialPort graps a thread pool thread and use this for the event. The test for ReceivedBytesThreshold is done in this thread and if the number is above the limit, your eventhandler is called. If not, the thread is just returned to the pool again.

     

    There are indeed two buffers in the system, but the SerialPort buffer is not used in case of bytes - only for encoded characters. BytesToRead shows the sum of bytes in the two buffers.

     

     

    Saturday, April 19, 2008 6:46 AM
  • Okay, I found the lock.  The ReceivedBytesThreshold is checked within this lock, just before running the DataReceived event.  There's a problem however if the binary data you receive contains a byte with value 0x1A.  SerialPort will call your event, regardless of how many bytes are available in the buffer.  To avoid this problem, write your event handler like this:

        private void SerialDataReceived(object sender, SerialDataReceivedEventArgs e) {
          if (e.EventType != SerialData.Chars) return;
          // Do your stuff
          // ...
        }

    Saturday, April 19, 2008 3:42 PM

All replies

  • There are two buffers in the system - one in the UART driver (default 4096 bytes) and one in SerialPort for use with encoded char and strings - but not for bytes. This is described in details in chapter "SerialPort Class" of this tutorial: http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm . The next chapter "SerialPort Events" describes the exact receiver sequence. Hope this helps in spite of the VB examples.

    Thursday, April 17, 2008 6:24 AM
  • No, they are talking about the exact same buffer.  If you use BytesToRead in your DataReceived event, you'll get in trouble.  ReceivedBytesThreshold only guarantees the minimum number of bytes in the buffer, there might be more.  There typically are more.  If you use BytesToRead or ReadExisting, you'll read more than 320 bytes.  That creates a problem for the next invocation of DataReceived which might already have been scheduled and might already have verified that there were at least 320 bytes.  It will run with less than 320 bytes available.

    By far the best solution is to simply not rely on ReceivedBytesThreshold.  Store the bytes you get in your own buffer and keep appending with each DataReceived event until you've got enough.
    Friday, April 18, 2008 8:18 PM
  • nobugz

     

    I don't think you are correct here. The two chapters in my totorial have been written on the basis of information I have got directly from Kim Hamilton - the one, who has programmed SerialPort. Have you actually read the two chapters? If not, please do.

     

    There is a mutual blocking (lock) between all event handlers (and close), which prevents more eventhandlers from running at the same time. Therefore a new handler for the DataReceived event will not run or be scheduled before the last one is terminated and the thread pool thread returned to the pool. When a DataReceived event occur, SerialPort graps a thread pool thread and use this for the event. The test for ReceivedBytesThreshold is done in this thread and if the number is above the limit, your eventhandler is called. If not, the thread is just returned to the pool again.

     

    There are indeed two buffers in the system, but the SerialPort buffer is not used in case of bytes - only for encoded characters. BytesToRead shows the sum of bytes in the two buffers.

     

     

    Saturday, April 19, 2008 6:46 AM
  • There is no lock.  A grave mistake.  Kim didn't write it.
    Saturday, April 19, 2008 10:12 AM
  • Yes there are a lock and Kim did write it! See this thread: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1379397&SiteID=1

     

    You actually participated in that thread yourself.

    Saturday, April 19, 2008 11:01 AM
  • Okay, I found the lock.  The ReceivedBytesThreshold is checked within this lock, just before running the DataReceived event.  There's a problem however if the binary data you receive contains a byte with value 0x1A.  SerialPort will call your event, regardless of how many bytes are available in the buffer.  To avoid this problem, write your event handler like this:

        private void SerialDataReceived(object sender, SerialDataReceivedEventArgs e) {
          if (e.EventType != SerialData.Chars) return;
          // Do your stuff
          // ...
        }

    Saturday, April 19, 2008 3:42 PM