3
votes

In a windows form application, on main form load, i have set a serial port and started reading it. The purpose is, as and when I receive some data on the serial port, I want to open another form related to the data.

So i use the DataReceived Event Handler of the serial port.

  void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

            string str = this.serialPort1.ReadLine();


                if (!string.IsNullOrEmpty(str))
                {


                    Main.Instance.customerData = new CustomerData(str);
                    Main.Instance.customerData.MdiParent = Main.Instance;  //Exeption received at this point
                    Main.Instance.customerData.Disposed += new EventHandler(customerData_Disposed);

                    Main.Instance.customerData.Show();


                }

        }

But when I try to open a form within the event handler it gives me an InvalidOperationExeption saying: "Cross-thread operation not valid: Control 'Main' accessed from a thread other than the thread it was created on."

I tried removing the code line : Main.Instance.customerData.MdiParent = Main.Instance; then it works fine. But its necessary also to assign the mdiparent in order to open it as a child form.

Any suggestions to resolve this problem ?

3

3 Answers

2
votes

Use the Invoke method on the Main form. You have to pass control over to the Main form to interact with it. The event handler is triggered on a background thread.

Here's some sample code that may work:

void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string str = this.serialPort1.ReadLine();
    if (!string.IsNullOrEmpty(str))
    {
        ShowCustomerData(str);
    }   

}

private delegate void ShowCustomerDataDelegate(string s);

private void ShowCustomerData(string s)
{
    if (Main.Instance.InvokeRequired)
    {
        Main.Instance.Invoke(new ShowCustomerDataDelegate(ShowCustomerData), s);
    }
    else
    {

        Main.Instance.customerData = new CustomerData(str);
        Main.Instance.customerData.MdiParent = Main.Instance;  //Exeption received at this point
        Main.Instance.customerData.Disposed += new EventHandler(customerData_Disposed);

        Main.Instance.customerData.Show();
    }
}
1
votes

Your event handler is not running on the UI thread. To get on the UI thread use the Invoke method of the main form.

1
votes

That is simply because a threading commandment in windows is "Thou shalt not access UI from any other thread but the UI thread"

So you need to use Control.Invoke to run code that Accesses UI on the UI thread.

//assuming your within a control and using C# 3 onward..
this.Invoke( () =>
 {
   //anything that UI goes here.
 }
);

A little Stackoverflow Ninja Google Search Would have helped you out. This happens to be a pretty infamous problem.

This answer seems to be almost exactly your problem: Cross-thread operation not valid while listening to a COM port