0

I have created:

private System.Windows.Forms.PictureBox [] RedBoxes;

Then in form_load, I do:

RedBoxes = new PictureBox[20];  
for (int i = 0; i < 20; i++)  
{  
    RedBoxes[i] = new PictureBox();  
    RedBoxes[i].Image = global::IDMTestClient.Properties.Resources.Red;  
    RedBoxes[i].Name = "RedBox" + i.ToString();  
    RedBoxes[i].Size = new Size(1, 38);  
    RedBoxes[i].Location = new Point(i + 10, 32);  
    RedBoxes[i].TabIndex = i + 2;  
    RedBoxes[i].TabStop = false;  
    groupBox3.Controls.Add(RedBoxes[i]);  
    RedBoxes[i].Visible = false;  
    RedBoxes[i].BringToFront();  
}  

Now when I try to access RedBoxes in another function, it throws an:

"A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll"

eg:
when I do:

RedBoxes[i].Left = 10;

or

RedBoxes[i].Location = new Point(10, 32);

What am I doing wrong?

/------------------UPDATE-------------------/

base {System.SystemException} = {"Cross-thread operation not valid: Control 'groupBox3' accessed from a thread other than the thread it was created on."}

This is what RedBoxes[i] has. The work of the WinForms auto generated threads?

Ram
  • 13
  • 3
  • @user633943 - where in the code are you doing these two actions, as they are not in the main code sample you posted? - sorry if this is a daft question – AMadmanTriumphs Feb 25 '11 at 10:41
  • Are you using threads? Please provide more sample code as @Digger asks so people won't have to keep guessing until someone gets it right. – Tedd Hansen Feb 25 '11 at 10:58
  • the first one (with the for loop) is in form1_load(); the place where i do the "RedBoxes[i].Location = new Point(10, 32);" is a member function of the form1. – Ram Feb 25 '11 at 11:06

2 Answers2

0

make sure that your other method is in the same Thread as the UI Thread. Changes from other threads are not allowed.

If its really another thread which invokes the method you can invoke the method to set the location like that:

This.Invoke(Delegate to method to invoke,arg as Object)
fixagon
  • 5,506
  • 22
  • 26
  • This should throw a MDA exception which is usually descriptive enough. – Tedd Hansen Feb 25 '11 at 10:57
  • The snippet that has the for-loop and the one in which I am trying to change the location are in in two different functions (both members of form1). The private System.Windows.Forms.PictureBox [] RedBoxes; is also, obviously, a member of 'form1' – Ram Feb 25 '11 at 11:05
  • @Tedd Hansen : And what is an MDA exception? – Ram Feb 25 '11 at 12:35
  • MDA (Managed Debugger Assistant) is something that came with VS2005 iirc. It helps you identify a lot of difficult to spot things like deadlocks, non-GUI threads working on GUI-objects, etc. Before this you would ship your application happily unaware and get calls from customers claiming that the app kept crashing at random places. – Tedd Hansen Feb 25 '11 at 15:04
0

Any change to the GUI must be done by the GUI thread. The GUI thread also needs to be free so it can check the Windows Message Queue and repaint the application now and then.

The solution is to invoke the GUI change whenever you need it, but keep background stuff in the background.

I've made a class that inherits Form that does this automatically: http://blog.tedd.no/index.php/2010/07/10/c-net-winforms-gui-thread-invoke-solution/

There you also see how to make the invoke.

private delegate void GUIInvokeMethodDelegate(Action @delegate);
/// 
/// Invoke command with GUI thread. Usage: GUIInvoke(() => FormOrControl.Cmd());
/// 
/// Command to execute in form: () => Cmd()
public void GUIInvokeMethod(Action @delegate)
{
    // Check if we need to invoke as GUI thread
    if (this.InvokeRequired)
    {
        this.Invoke(new GUIInvokeMethodDelegate(GUIInvokeMethod), @delegate);
        return;
    }

    // Execute
    @delegate.Invoke();
}

public void DoThisAsGUI() 
{
    GUIInvokeMethod(() => 
    {
        // Something you want to do in GUI thread. 
    }); 
    // or
    GUIInvokeMethod(() => SomeMethodThatRequiresGUIThread());
}

Note that you can change "this" with an instance of a Form for example.

Tedd Hansen
  • 12,074
  • 14
  • 61
  • 97