Home>

We are developing a system with WindowsForm.
Serial communication via USB connection so that users can understand the situation
I am trying to implement the textbox so that AppendText can confirm the operation.

Error message

Individual confirmation of serial communication connection, data reception, and data writing has been confirmed to work without problems.
However, if AppendText is applied to TextBox during data reception or data writing, an error occurs and the expected operation cannot be performed.
↓ Error messages will be listed as soon as they can be confirmed.

Error message
Applicable source code
public partial class DataRelayForm: Form
{
    private static log4net.ILog logger = log4net.LogManager.GetLogger (MethodBase.GetCurrentMethod (). DeclaringType);
    private SerialPort serialPort;
    public DataRelayForm ()
    {
        InitializeComponent ();
    }
    ///<summary>
    /// Form loading event
    ///</summary>
    ///<param name = "sender"></param>
    ///<param name = "e"></param>
    private void DataRelayForm_Load (object sender, EventArgs e)
    {
        string [] ports = SerialPort.GetPortNames ();
        foreach (string port in ports)
        {
            this.cmbSerials.Items.Add (port);
        }
        if (0<this.cmbSerials.Items.Count)
        {
            this.cmbSerials.SelectedIndex = 0;
        }
    }
    ///<summary>
    /// event when connect button is pressed
    ///</summary>
    ///<param name = "sender"></param>
    ///<param name = "e"></param>
    private void btnConnect_clicked (object sender, EventArgs e)
    {
        if (this.cmbSerials.SelectedItem! = null)
        {
            // OPEN COM port
            serialPort = new SerialPort ();
            serialPort.DataReceived + = new SerialDataReceivedEventHandler (SerialPort1_DataReceived);
            serialPort.PortName = this.cmbSerials.SelectedItem.ToString ();serialPort.BaudRate = 9600;
            serialPort.DataBits = 8;
            serialPort.Parity = Parity.None;
            serialPort.StopBits = StopBits.One;
            serialPort.Encoding = Encoding.UTF8;
            serialPort.DtrEnable = true;
            serialPort.RtsEnable = true;
            // Set the remote device name
            int iName = int.Parse (serialPort.PortName.Replace ("COM", ""));
            sComName = iName.ToString ("0000");
            // start connection
            try
            {
                serialPort.Open ();
                // Output to log file&screen
                string sLogData = Properties.Resources.Log_Start;
                logger.Info (sLogData);
                this.txtLog.AppendText (DateTime.Now + "" + sLogData + Environment.NewLine);
            }
            catch (Exception ex)
            {
                logger.Error (ex.Message);
                this.txtLog.AppendText (DateTime.Now + "" + ex.Message + Environment.NewLine);
            }
        }
    }
    ///<summary>
    /// Data reception event
    ///</summary>
    ///<param name = "sender"></param>
    ///<param name = "e"></param>
    private void SerialPort1_DataReceived (object sender, SerialDataReceivedEventArgs e)
    {
        if (serialPort! = null&&serialPort.IsOpen)
        {
            try
            {
                // Read received data
                SerialPort sp = (SerialPort) sender;
                string sChildData = sp.ReadExisting ();
                logger.Info ("Data received");
                this.txtLog.AppendText (DateTime.Now + ": Data received" + Environment.NewLine);
            }
            catch (Exception ex)
            {
                logger.Error (ex.Message);
                this.txtLog.AppendText (DateTime.Now + "" + ex.Message + Environment.NewLine);
            }}
    }
    ///<summary>
    /// Data writing process
    ///</summary>
    ///<param name = "command"></param>
    private bool DataWrite (string buff)
    {
        try
        {
            serialPort.Write (buff);
            while (0<serialPort.WriteTimeout) {}
            this.txtLog.AppendText (DateTime.Now + "Send data:" + buff + Environment.NewLine);
            return true;
        }
        catch (IOException ex)
        {
            return false;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    ///<summary>
    /// Event when the end button is pressed
    ///</summary>
    ///<param name = "sender"></param>
    ///<param name = "e"></param>
    private void btnFinish_clicked (object sender, EventArgs e)
    {
        // connected
        if (serialPort! = null&&serialPort.IsOpen)
        {
            // disconnect
            serialPort.Close ();
            serialPort = null;
            // Output to log file&screen
            string sLogData = Properties.Resources.Log_End;
            logger.Info (sLogData);
            this.txtLog.AppendText (DateTime.Now + "" + sLogData + Environment.NewLine);
        }
    }
}
Supplemental information (FW/tool version etc.)

Windows10, c #, VisualStudio

  • Answer # 1

    Cause

    MaybeInvalidOperationExceptionoccurred because you tried to draw the screen withAppendTextfrom outside the main thread.

    InvalidOperationExceptionis an exception that occurs when a thread other than the thread that created the control accesses the control.

    In the posted code,SerialPort1_DataReceivedis called from a non-user input event and the worker thread is processing, so I think that an exception has occurred.

    * If you don't understand the meaning of the above sentence, use C #

    Multi-thread programming

    Main thread (UI thread)

    Worker thread (background thread)

    Search for

    .

    Solution

    Delegates the part that accesses the control (this.txtLog.AppendText (DateTime.Now + ": Data received" + Environment.NewLine);etc.) to themain thread

    Use the Control.Invoke method to delegate processing to the main thread.

    Reference

    How can I operate the control from another thread in Windows Form?
    How to operate form controls from another thread?
    Display a form from a C # subthread (Invoke

  • Answer # 2

    SerialPort.DataReceived event
    As you can see, this event occurs on the secondary thread.
    So you need to Invoke.