serialport continuous real time data c#

11,243

Here is one solution.

The serial port is receiving the data in its own thread, and you should read the incoming bytes in the data received handler.

I propose to read the data and add it to a thread-safe FIFO list in the data received handler and read the data from the list in the main thread.

See my solution in post Serial port reading + Threads or something better?

Share:
11,243
pgwri
Author by

pgwri

Updated on June 04, 2022

Comments

  • pgwri
    pgwri almost 2 years

    Hi I'm trying to program a simple C# WPF that displays time information on a virtual scoreboard in real time from a timing system. I'm fairly new to programming so in depth explanation would be appreciated.

    I have created a new thread to handle the incoming data from the COM port and as the app is developed this data will be interpreted. For now I just wanted to display the raw information (in hex) that is coming from the timer into a textbox. This works but not as intended. I am receiving tons of duplicate information, my only explanation is I am reading the data too slowly or its reading the same byte over and over. What I would like to happen is to take out each byte and display them, all controlled by one start/stop button.

    Possible solutions include storing the entire buffer in a list or array which I'm not quite sure of yet, I don't want to add so many threads that the program freezes everything up.

    Here is my code so far (I'm new to pretty much all the code I have written here, so if anything is bad practice please let me know):

    public partial class MainWindow : Window
    {
        SerialPort comms;
        Thread commThread;
    
        bool flag;
        string message;
    
    
        public MainWindow()
        {
            InitializeComponent();
            comms = new SerialPort();
        }
    
        private void PortControl_Click(object sender, RoutedEventArgs e)
        {
            if (!comms.IsOpen)
            {
                PortControl.Content = "Stop";
                comms.PortName = "COM1";
                comms.BaudRate = 9600;
                comms.DataBits = 8;
                comms.StopBits = StopBits.One;
                comms.Parity = Parity.Even;
                comms.ReadTimeout = 500;
                comms.ReceivedBytesThreshold = 1;
    
                commThread = new Thread(new ThreadStart(Handle));
    
                comms.Open();
    
                comms.DataReceived += new SerialDataReceivedEventHandler(ReadIn);
            }
            else
            {
                PortControl.Content = "Start";
                flag = false;
                comms.DataReceived -= ReadIn;
    
                commThread.Join();
                comms.Close();
            }
        }
    
        private void ReadIn(object sender, SerialDataReceivedEventArgs e)
        {
            if (!commThread.IsAlive)
            {
                flag = true;
                commThread.Start();
            }
        }
    
          private void Handle()
          {
              while (flag)
              {
                  if (comms.IsOpen)
                  {
                      try
                      {
                          message = comms.ReadByte().ToString("X2");
    
                          Dispatcher.BeginInvoke((Action)(() =>
                          {
                              ConsoleBox.Text += message + " ";
                          }));
                      }
                      catch (Exception ex)
                      {
                          MessageBox.Show(ex.ToString());
                      }
                  }
              }
          }
    
    
    }
    
  • pgwri
    pgwri almost 11 years
    Hi thanks for the response. I attempted to use your idea and it has worked to an extent, I implemented a timer to display the data, however it only displays my data for the first tick, and then when I try to stop it, the application freezes. The hex that I am getting through looks correct though.
  • user2019047
    user2019047 almost 11 years
    When you enter the timer tick handler, stop the timer before calling the routine to empty the queue. When the queue is empty and the routine returns, enable the timer again. That is what I do to make sure the timer tick event is not called too early.
  • pgwri
    pgwri almost 11 years
    Thank you! I was able to get it working smoothly by taking everything out of the queue and putting it into another intermediate array to prevent the deadlocking, and then using stringbuilder to display the data. Onto the next step!
  • user2019047
    user2019047 almost 11 years
    Great! I have a timer event every 10 millisecond for an application that receives data from a micro controller. The serial port is set to 9600 baud, and the queue never gets really big, but then I queue a struct with the received characters instead of one character at a time, it makes for more efficient de-queuing.