0

I have a program which relies on data being sent through a serial port. I would like to monitor when data is sent through with SerialPort.ReadLine(). My problem is that I use check boxes which freeze when checked because the SerialPort.ReadLine() method blocks until it receives some data. I have also tried using ReadTimeout() but it did not work; perhaps because I did not use it correctly.

I've posted my code for this event below. What I would like this method to do is to monitor my serial port when the checkbox is checked, and then stop monitoring the serial port when I un-check the box. My current situation with my code is that it freezes upon checking the box. All help is appreciated.

private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox1.Checked)
        {
            checkBox1.Text = "Listening...";
            using (SerialPort arduino = new SerialPort())
            {
                arduino.BaudRate = 9600;
                arduino.PortName = comboBox1.Text;
                arduino.Open();

                string pipe = arduino.ReadLine(); //loop here

                if (pipe == "S")
                {
                    //System.Diagnostics.Process.Start("shutdown", "/f /r /t 0");
                    System.Windows.Forms.Application.Exit();
                }


                else
                {
                    checkBox1.Text = "Start";
                }
            }
        }
    }
  • ReadLine is not made to monitor when data is sent. The SerialPort class has an event for this . You should open the port in advance and use the DataReceived event. Doing this your GUI will not freeze – Mong Zhu Aug 21 '16 at 19:48
  • For GUI programs, operations that can block need to be done asynchronously, to ensure the UI thread remains responsive. See the marked duplicate for one approach. See https://stackoverflow.com/questions/5468039/cross-thread-operation-not-valid-while-reading-data-on-serial-port to anticipate your next question about how to access the UI from the asynchronous completion. Note that if you use `async` and `await` with the async API, you won't need to deal with the cross-thread aspect, as the `await` statement will do that automatically. – Peter Duniho Aug 21 '16 at 20:10
  • @PeterDuniho I wonder whether the answer from the dublicate will help Alexander Stroborg. I would not say that using the asynch await approach is necessary here. Although it surely is an elegant way, but also not easily graspable for beginners. Using the `DataReceived` event would suffice in this case to solve the problem and still make the GUI remain responsive – Mong Zhu Aug 21 '16 at 20:33
  • 1
    @Mong: using `DataReceived` is fine too, but also adequately addressed in a variety of existing Q&A on Stack Overflow. Using it also requires comprehending and applying techniques for dealing with cross-thread access to UI components (per my other link above), while `await` does not. Frankly, I think `await` is probably _easier_ for beginners to learn, as they have no incorrect preconceptions to interfere with their learning the newer technique, while the newer technique is specifically designed to remove from view much of the headaches normally involved in dealing with async code. – Peter Duniho Aug 21 '16 at 20:45

1 Answers1

0

Consider using the SerialPort.DataReceived event instead of blocking.

seairth
  • 1,966
  • 15
  • 22