【问题标题】:Cannot access picturebox array无法访问图片框数组
【发布时间】:2011-02-25 10:23:51
【问题描述】:

我已经创建了:

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();  
}  

现在,当我尝试在另一个函数中访问 RedBoxes 时,它会抛出:

“System.Windows.Forms.dll 中发生了“System.InvalidOperationException”类型的第一次机会异常”

例如:
当我这样做时:

RedBoxes[i].Left = 10;

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

我做错了什么?

/------------------更新------- em>/

base {System.SystemException} = {"跨线程操作无效:控件'groupBox3'从创建它的线程以外的线程访问。"}

这就是 RedBoxes[i] 所拥有的。 WinForms 自动生成线程的工作原理?

【问题讨论】:

  • @user633943 - 您在代码中的哪个位置执行这两个操作,因为它们不在您发布的主代码示例中? - 对不起,如果这是一个愚蠢的问题
  • 你在使用线程吗?请按照@Digger 的要求提供更多示例代码,这样人们就不必一直猜测,直到有人猜对了。
  • 第一个(带有for循环)在form1_load()中;我做“RedBoxes[i].Location = new Point(10, 32);”的地方是 form1 的成员函数。

标签: c# winforms arrays dynamic picturebox


【解决方案1】:

对 GUI 的任何更改都必须由 GUI 线程完成。 GUI 线程也需要空闲,以便它可以检查 Windows 消息队列并不时重绘应用程序。

解决方案是在需要时调用 GUI 更改,但将背景内容保留在后台。

我创建了一个继承 Form 自动执行此操作的类: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”。

【讨论】:

    【解决方案2】:

    确保您的其他方法与 UI 线程位于同一线程中。不允许从其他线程进行更改。

    如果它确实是另一个调用该方法的线程,您可以调用该方法来设置位置:

    This.Invoke(Delegate to method to invoke,arg as Object)
    

    【讨论】:

    • 这应该会抛出一个 MDA 异常,该异常通常足够描述。
    • 具有 for 循环的 sn-p 和我试图更改位置的 sn-p 位于两个不同的函数中(都是 form1 的成员)。私有 System.Windows.Forms.PictureBox [] RedBoxes;显然,它也是“form1”的成员
    • @Tedd Hansen:什么是 MDA 异常?
    • MDA(托管调试器助手)是 VS2005 iirc 附带的。它可以帮助您识别很多难以发现的问题,例如死锁、在 GUI 对象上工作的非 GUI 线程等。在此之前,您会愉快地发布您的应用程序而不知道并接到客户的电话,声称该应用程序总是在随机的地方崩溃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多