3
votes

I am working on code that connects to a serial port of a stepper motor. I send a command to the stepper motor via textBox2 and am attempting to read in the return data from the command to textBox3. I am able to make a connection, send the command, and receive the data. But after my GUI populates textBox3 with the returned serial data it freezes.

I believe that the code is getting stuck in the try loop but I don't know how to break out of it. Here is my code:

private void button3_Click(object sender, EventArgs e)
{
    if (isConnectedMotor)
    {
        string command = textBox2.Text;
        portMotor.Write(command + "\r\n");
        portMotor.DiscardInBuffer();

        while (true)
        {
            try
            {
                string return_data = portMotor.ReadLine();
                textBox3.AppendText(return_data);
                textBox3.AppendText(Environment.NewLine);
            }
            catch(TimeoutException)
            {
                break;
            }
        }       
    }
}

DataReceived Code:

private void connectToMotor()
{
    isConnectedMotor = true;
    string selectedPort = comboBox2.GetItemText(comboBox2.SelectedItem);
    portMotor = new SerialPort(selectedPort, 9600, Parity.None, 8, StopBits.One);
    portMotor.RtsEnable = true;
    portMotor.DtrEnable = true;
    portMotor.Open();
    portMotor.DiscardInBuffer();
    portMotor.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    button4.Text = "Disconnect";
    enableControlsMotor();
}

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    textBox3.AppendText(indata);
    textBox3.AppendText(Environment.NewLine);
}

I am getting an error saying:

An object reference is required for the non-static field, method, or property 'Form1.textBox3'

Invoke code:

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {

        portMotor.DiscardInBuffer();
        incoming_data = portMotor.ReadExisting();
        this.Invoke(new EventHandler(displayText));
    }

    private void displayText(object o, EventArgs e)
    {
        textBox3.Text += incoming_data;
    }
1
You have an infinite loop. Why would you expect it do anything other than get stuck? Also, ReadLine() is a blocking call. It'll pause execution until a newline is received.3Dave
@3dave in my question, I ask how to to break out of the infinite loop.colinodowd
Yes. The answer is don't enter an infinite loop.3Dave

1 Answers

3
votes

Instead of looping to read data, use a DataReceived event to get at the incoming bytes asynchronously.

See the documentation and example. Also see this question for troubleshooting.

P.S. Here is a code sample to avoid locking up the UI.

private void ReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
    var incoming_data = portMotor.ReadExisting();

    // this is executing on a separate thread - so throw it on the UI thread
    Invoke(new Action(() => {
        textBox3.Text += incoming_data;
    }));
}