0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;



namespace SerialPort
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            cmdClose.Enabled = false;
            foreach (String s in System.IO.Ports.SerialPort.GetPortNames()) 
            {
                txtPort.Items.Add(s);
            }
        }

    public System.IO.Ports.SerialPort sport;

    public void serialport_connect(String port, int baudrate , Parity parity, int databits, StopBits stopbits) 
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();

        sport = new System.IO.Ports.SerialPort(
        port, baudrate, parity, databits, stopbits);
        try
        {
            sport.Open();
            cmdClose.Enabled = true;
            cmdConnect.Enabled = false;
            txtReceive.AppendText("[" + dtn + "] " + "Connected\n");
            sport.DataReceived += new SerialDataReceivedEventHandler(sport_DataReceived);
        }
        catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
    }

    private void sport_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        txtReceive.AppendText("["+dtn+"] "+"Received: "+sport.ReadExisting()+"\n");
    }

    private void cmdConnect_Click(object sender, EventArgs e)
    {
        String port = txtPort.Text;
        int baudrate = Convert.ToInt32(cmbbaudrate.Text);
        Parity parity = (Parity)Enum.Parse(typeof(Parity), cmbparity.Text);
        int databits = Convert.ToInt32(cmbdatabits.Text);
        StopBits stopbits = (StopBits)Enum.Parse(typeof(StopBits), cmbstopbits.Text);

        serialport_connect(port, baudrate, parity, databits, stopbits);

    }

    private void button1_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String data = txtDatatoSend.Text;
        sport.Write(data);
        txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
    }

    private void cmdClose_Click_1(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();

        if (sport.IsOpen) 
        {
            sport.Close();
            cmdClose.Enabled = false;
            cmdConnect.Enabled = true;
            txtReceive.AppendText("[" + dtn + "] " + "Disconnected\n");
        }
    }
}

}

Hi all, I get into trouble with thrown InvalidOperationException when I try to set my Baud rate from 9600 to 115200. enter image description here enter image description here

Any idea why that is? Thanks in advance.

Willie Cheng
  • 7,679
  • 13
  • 55
  • 68
ZoeY
  • 11
  • 5
  • Your event handler runs on a different thread than the UI, so you cant access the UI's controls from that thread, you need to create a delegate to call from your event handler which can access the UI's controls – BackDoorNoBaby May 18 '16 at 20:45
  • Thanks for your reply! I get rid of that problem now. – ZoeY May 18 '16 at 21:11

1 Answers1

1

What's happening here is that you are getting a serial port callback from a non-UI thread, and in that callback you are trying to change a UI component.

You're not allowed to do that, and you'll get the exception you're seeing.

The best solution to this depends on what version of .Net you're using, but whatever version you're using you can always use Control.BeginInvoke() to solve it.

There's some sample code on the link I provided.

Note that it's not setting the baud rate that's causing the problem. It's the code in sport_DataReceived() that tries to update a UI component (which you can see from the second image you posted).

You can probably change that function as follows:

private void sport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    this.BeginInvoke(new Action(() =>
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        txtReceive.AppendText("[" + dtn + "] " + "Received: " + sport.ReadExisting() + "\n");
    }));
}

What this does is cause the code for the Action above to be called on the UI thread.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • thank you so much for your reply, now I get rid of that exception. Now I am trying to type in command "!G 1 500" to control the short arm of my robot to rotate horizontally, it doesn't work. (If I use Roboteq to control it, it will work, so there is no problem with any commands or building of robots). Do you think it has something to do with carriage return? or the delay time or something? Any suggestion? Thank you! – ZoeY May 18 '16 at 21:09
  • @ZoeY I'm afraid I don't know the answer to that part. Perhaps you should make a new question, and someone else might know. – Matthew Watson May 19 '16 at 06:43
  • can you please see my [question](https://stackoverflow.com/q/64203396/6854117) related to it? – Moeez Oct 05 '20 at 07:00