我创建了:
private System.Windows.Forms.PictureBox [] RedBoxes;
然后在form_load中,我这样做:
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();
}
现在,当我尝试在另一个函数中访问RedBox时,它会抛出:
“System.Windows.Forms.dll中出现'System.InvalidOperationException'类型的第一次机会异常”
例如:
当我这样做时:
RedBoxes[i].Left = 10;
或
RedBoxes[i].Location = new Point(10, 32);
我做错了什么?
/ ------------------ UPDATE ------------------- /
base {System.SystemException} = {“跨线程操作无效:控制'groupBox3'从其创建的线程以外的线程访问。”}
这就是RedBoxes [i]的含义。 WinForms自动生成线程的工作?
答案 0 :(得分:0)
确保您的其他方法与UI线程位于同一个线程中。不允许对其他线程进行更改。
如果它真的是另一个调用该方法的线程,你可以调用该方法来设置这样的位置:
This.Invoke(Delegate to method to invoke,arg as Object)
答案 1 :(得分:0)
GUI的任何更改都必须由GUI线程完成。 GUI线程也需要是免费的,因此它可以检查Windows消息队列并立即重新绘制应用程序。
解决方案是在需要时调用GUI更改,但将后台内容保留在后台。
我创建了一个继承自动执行此操作的表的类:http://blog.tedd.no/index.php/2010/07/10/c-net-winforms-gui-thread-invoke-solution/
在那里你也看到了如何进行调用。
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());
}
请注意,您可以使用Form的实例更改“this”。