代码之家  ›  专栏  ›  技术社区  ›  Roast

关闭或隐藏窗体会导致跨线程错误

  •  4
  • Roast  · 技术社区  · 16 年前

    这个简单的任务让我一次又一次地感到困惑。

    我有一系列的子窗体。数组在另一个窗体的构造函数中初始化:

    frmChildren = new ChildGUI[20];
    

    当用户请求查看子窗体时,我执行以下操作:

    if (frmChildren[nb] == null)
    {
        frmChildren[nb] = new ChildGUI();
        frmChildren[nb].MdiParent = this.MdiParent;
    }
    frmChildren[nb].Show();
    

    作品

            for (int i = 0; i < frmChildren.Length;i++ )
            {
                if (frmChildren[i] != null)
                {
                    //frmChildren[i].BeginInvoke(new EventHandler(delegate
                    //{
                        frmChildren[i].Close();
                    //}));
                }
            }             
            frmChildren= new ChildGUI[20];
    

    我在.Close()上遇到了一个跨线程异常。注意,我已经尝试过调用,但是这样做会绕过=因为某些原因无效。我想这可能和垃圾收集器有关。有人有意见吗?

    1 回复  |  直到 12 年前
        1
  •  9
  •   Jon Skeet    16 年前

    i -所以到了 事实上 在UI线程中调用,您得到了一个不同的值 我 ,可以为空。试试这个:

    for (int i = 0; i < frmChildren.Length; i++)
    {
        ChildGUI control = frmChildren[i];
        if (control != null)
        {
            control.BeginInvoke(new EventHandler(delegate
            {
                control.Close();
            }));
        }
    }             
    frmChildren = new ChildGUI[20];
    

    看见 Eric Lippert's blog post 在内部 循环解决了问题。

    编辑:如果你想使用 foreach 循环,看起来是这样的:

    foreach (ChildGUI control in frmChildren)
    {
        // Create a "new" variable to be captured
        ChildGUI copy = control;
        if (copy != null)
        {
            copy.BeginInvoke(new EventHandler(delegate
            {
                copy.Close();
            }));
        }
    }             
    frmChildren = new ChildGUI[20];
    

    foreach (ChildGUI control in frmChildren)
    {
        if (control != null)
        {
            control.BeginInvoke(new MethodInvoker(control.Close));
        }
    }             
    frmChildren = new ChildGUI[20];