Search code examples
c#serial-port.net-4.5

What is the correct way to read a serial port using .NET framework?


I've read a lot of questions here about how to read data from serial ports using the .NET SerialPort class but none of the recommended approaches have proven completely efficient for me.

Here is the code I am using for now:

SerialPort port = new SerialPort("COM1");
port.DataReceived += new SerialDataReceivedEventHandler(MyDataReceivedHandler);

And the event handler:

void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    int count = port.BytesToRead;
    byte[] ByteArray = new byte[count];
    port.Read(ByteArray, 0, count);
}

But I am still sometimes missing data. I've tried different way of reading the data in the event handler but with no luck.

As the .NET 4.5 brings new possibilities to do some asynchronous tasks, like with the ReadAsync method that seems to be useable on a SerialPort stream, I'm curious to see what would be the recommended approach to handle those cases.


Solution

  • Could you try something like this for example I think what you are wanting to utilize is the port.ReadExisting() Method

     using System;
     using System.IO.Ports;
    
     class SerialPortProgram 
     { 
      // Create the serial port with basic settings 
        private SerialPort port = new   SerialPort("COM1",
          9600, Parity.None, 8, StopBits.One); 
        [STAThread] 
        static void Main(string[] args) 
        { 
          // Instatiate this 
          SerialPortProgram(); 
        } 
    
        private static void SerialPortProgram() 
        { 
            Console.WriteLine("Incoming Data:");
             // Attach a method to be called when there
             // is data waiting in the port's buffer 
            port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
            // Begin communications 
            port.Open(); 
            // Enter an application loop to keep this thread alive 
            Console.ReadLine();
         } 
    
        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
        { 
           // Show all the incoming data in the port's buffer
           Console.WriteLine(port.ReadExisting()); 
        } 
    }
    

    Or is you want to do it based on what you were trying to do , you can try this

    public class MySerialReader : IDisposable
    {
      private SerialPort serialPort;
      private Queue<byte> recievedData = new Queue<byte>();
    
      public MySerialReader()
      {
        serialPort = new SerialPort();
        serialPort.Open();
        serialPort.DataReceived += serialPort_DataReceived;
      }
    
      void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e)
      {
        byte[] data = new byte[serialPort.BytesToRead];
        serialPort.Read(data, 0, data.Length);
        data.ToList().ForEach(b => recievedData.Enqueue(b));
        processData();
      }
    
      void processData()
      {
        // Determine if we have a "packet" in the queue
        if (recievedData.Count > 50)
        {
            var packet = Enumerable.Range(0, 50).Select(i => recievedData.Dequeue());
        }
      }
    
      public void Dispose()
      {
            if (serialPort != null)
            {
                serialPort.Dispose();
            }
      }