2

This is a small method I have on Form2 to set up some component's states. When I call it from Form2 on Load it ofc. works fine, but when I call it from Form1 (needs to update some states) I get an exception:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

Additional information: Cross-thread operation not valid: Control 'button1' accessed from a thread other than the thread it was created on.

public void SetleMotor1()
{
    button1.Enabled = true;
    button2.Enabled = false;
    if (Form1.Motor1.Calibstate == 3)
        label4.Text = "Befejezve";
    else
        label5.Text = "Megállt";

    if (Form1.Motor1.Calibrated)
    {
        label21.Text = "Igen";
        label6.Text = Convert.ToString(Form1.Motor1.MMImp);
    }
    else
    {
        label21.Text = "Nem";
        label6.Text = "-";
    }
}

Please, what am I missing here?

Here is the code from Form1 that calls the method on Form2:

void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // reading the data etc etc etc...then evaluating:
    case 1:
        if ((data[1] == 40) && (Motor1.Calibstate == 3))
        {
            long impulses = (65536 * data[2] + 256 * data[3] + data[4]);
            Form2.SetleMotor1(); // <----- this is where it happens
            Motor1.Calibstate = 0;
            zaloguj("A Motor 1 kalibrációja befejezve");
            if (Motor1.Debug)
                zaloguj("A Motor 1 köre " + Convert.ToString(impulses) + " impulzus");

            Motor1.MMImp = Convert.ToInt32(impulses / 360);
            Motor1.Calibrated = true;
            if (Motor1.Debug)
                zaloguj("M1Imp/deg: " + Convert.ToString(Motor1.MMImp));
        }
        break;
        // other similar code ...
}
Mo Patel
  • 2,321
  • 4
  • 22
  • 37
Istvan Prosinger
  • 145
  • 2
  • 11
  • you could place here the code where you call the method please. – terrybozzio Aug 28 '13 at 22:39
  • possible duplicate of [Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on](http://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) – Chris Sinclair Aug 28 '13 at 22:40
  • 1
    Also please tell us if you are creating the `button` in the designer, or in code? And if in code, show us that too. – Daniel Gabriel Aug 28 '13 at 22:41
  • All is created in the designer, I nearly change the already created object's properties. I'm calling this code form the Serial Port event handler (I use the standard serial port given in Visual Studio) on Form1. It's probabbly a thread polling the COM port's status, I didn't realize that before. The code (serial port handler) is rather long but I'll paste the inportant part in a few hours, as soon as I get to my laptop). – Istvan Prosinger Aug 29 '13 at 10:55
  • There's a global variable Form1.Motor1.Calibstate - I was thinking of subscribing the event of it's value change or something similar and handling it on Form2...would that work? – Istvan Prosinger Aug 29 '13 at 17:03

1 Answers1

7

You need to invoke the method call on the form's thread. You can make the method do it itself so you don't have to worry about it in the calling code:

public void SetleMotor1()
{
    if (Form1.InvokeRequired)
    {
        Form1.Invoke(new Action(SetleMotor1));
        return;
    }

    button1.Enabled = true;
    button2.Enabled = false;
    if (Form1.Motor1.Calibstate == 3)
        label4.Text = "Befejezve";
    else
        label5.Text = "Megállt";
    if (Form1.Motor1.Calibrated)
    {
        label21.Text = "Igen";
        label6.Text = Convert.ToString(Form1.Motor1.MMImp);
    }
    else
    {
        label21.Text = "Nem";
        label6.Text = "-";
    }
}
Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
  • Thanks for the answer. "I get the The best overloaded method match has some invalid arguments" error for this code – Istvan Prosinger Aug 29 '13 at 16:39
  • @IstvanProsinger, thanks for pointing it out. Seems `Invoke` doesn't support passing a lambda to it directly, so wrap in `Action`. I corrected the answer. – Samuel Neff Aug 29 '13 at 23:03
  • OK, I had to create an instance of Form1 for my case, except that, Your code worked perfectly. Thanks @Samuel Neff – Istvan Prosinger Aug 31 '13 at 07:39