views:

94

answers:

3

Hi, I am trying to pass 2 variables from a thread, in the MainForm, to another form, but when doing so an error occurs.

private void TrackingThread( )
    {
        float targetX = 0;
        float targetY = 0;

        while ( true )
        {
            camera1Acquired.WaitOne( );
            camera2Acquired.WaitOne( );

            lock ( this )
            {
                // stop the thread if it was signaled
                if ( ( x1 == -1 ) && ( y1 == -1 ) && ( x2 == -1 ) && ( y2 == -1 ) )
                {
                    break;
                }

                // get middle point
                targetX = ( x1 + x2 ) / 2;
                targetY = ( y1 + y2 ) / 2;
            }

            if (directionForm != null)
            {
                directionForm.RunMotors(targetX, targetY);
            }
        }
    }

In the form, directionForm, I am simply displaying the variables targetX and targetY. The code for the directionForm.RunMotors() is the following:

public void RunMotors(float x, float y)
    {
        label1.Text = "X-ordinate " + x.ToString();
        label2.Text = "Y-ordinate " + y.ToString();
    }

The error happen when I am trying to display the two variables: "InvalidOperationException was unhandled Cross-threading operation not valid: Control label1 accessed from a thread other than . the thread it was created on"

What shall I do???

Thanks in advance

+5  A: 

The entire GUI is not thread-safe, the error you see is an intentional check. You have to pass the method to the messagepump to have it executed on the main thread. Use something like:

if (directionForm != null)            
{
   var a = new Action<float, float>(RunMotors);
   directionForm.Invoke(a, targetX, targetY);
}
Henk Holterman
A: 

you have to Upate your UI from the UI Thread. Invoke a method in the UI Thread. It's basicly the same as Henk Holterman wrote. The UpdateUIDelegate must have the same signature than your RunMotors Method.

void UpdateUI() {
    if (this.yourControl.InvokeRequired) {
        object[] ob = new object[] { targetX, targetY };
        UpdateUIDelegate updDel = new UpdateUIDelegate(RunMotors);
        this.yourControl.Invoke(updDel, ob);
    }
    else {
        this.RunMotors(targetX, targetY);
    }
}

void RunMotors(targetX, targetY)
{
    // action
}
chriszero
Since it is given that the call is always from another Thread you might as well skip the `if (InvokeRequired)` logic.
Henk Holterman
A: 

Simple Solution to Illegal Cross-thread Calls

Also check Control.CheckForIllegalCrossThreadCalls Property.

When a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results. A common invalid thread activity is a call on the wrong thread that accesses the control's Handle property. Set CheckForIllegalCrossThreadCalls to true to find and diagnose this thread activity more easily while debugging. Note that illegal cross-thread calls will always raise an exception when an application is started outside the debugger.

KMan