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 w开发者_Python百科hen 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?
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.
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)
精彩评论