views:

148

answers:

3

This code is executed by many way. When it's executed by the form button it works (the button start a thread and in the loop it call this method = it works). BUT it doesn't work when I have a call to that method from my BackgroundWorker in the form.

With the following code:

private void resizeThreadSafe(int width, int height)
{
    if (this.form.InvokeRequired)
    {
        this.form.Invoke(new DelegateSize(resizeThreadSafe),
            new object[] { width, height });
    }
    this.form.Size = new Size(width, height); // problem occurs on this line
    this.form.Location = new Point(0, 0); // dummy coordinate
}

Then on the line containing this.form.Size = ... I get the following exception:

InvalidOperationException was unhandled
Cross-thread operation not valid: Control 'Form1' accessed from a thread other
than the thread it was created on.

Why?

+6  A: 

You need to return at the end of the if block - otherwise you'll resize it in the right thread, and then do it in the wrong thread as well.

In other words (if you'd cut and paste the code instead of a picture, this would have been easier...)

private void resizeThreadSafe(int width, int height)
{
    if (this.form.InvokeRequired)
    {
        this.form.Invoke(new DelegateSize(resizeThreadSafe,
            new object[] { width, height });
        return;
    }
    this.form.Size = new Size(width, height);
    this.form.Location = new Point(0, SystemInformation.MonitorSize // whatever comes next
}

Alternatively just put the second half of the method in an "else" block.

Jon Skeet
+1  A: 

You need write this:

if ( this.form.InvokeRequired ) {
    this.form.Invoke( ...... );
    return;
}
this.form.Size = new Sizte( ... );

OR

if ( this.form.InvokeRequired ) {
    this.form.Invoke( ...... );
}
else {
    this.form.Size = new Sizte( ... );
}
TcKs
+1  A: 

Depending on your coding style either use return right after the Invoke or put the actual action as an else block.

dr. evil