关闭或隐藏表单会导致交叉线程错误

Roa*_*ast 4 .net c# winforms

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

我有一系列子表单.该数组在另一个窗体的构造函数中启动:

frmChildren = new ChildGUI[20];
Run Code Online (Sandbox Code Playgroud)

当用户请求查看子表单时,我这样做:

if (frmChildren[nb] == null)
{
    frmChildren[nb] = new ChildGUI();
    frmChildren[nb].MdiParent = this.MdiParent;
}
frmChildren[nb].Show();
Run Code Online (Sandbox Code Playgroud)

到目前为止这个工作.在后台我可以下载这些表单的新内容.下载完成后,我将触发ChildChange事件.这是它停止工作的地方.我只想关闭/隐藏任何形式打开然后重新生成一组新的-frmChildren = new ChildGUI [20]; - 这是许多试验之一:

        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];
Run Code Online (Sandbox Code Playgroud)

我在.Close()上遇到了Cross Thread异常.注意我已经尝试过调用,但这样做会因某种原因绕过!= null.我认为它可能与垃圾收集器有关.有人有输入吗?

Jon*_*eet 9

问题是你的匿名方法正在捕获i- 所以当它在UI线程中实际调用时,你有一个不同的值i,可能是null.试试这个:

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];
Run Code Online (Sandbox Code Playgroud)

请参阅Eric Lippert的博客文章,了解为什么循环中引入新变量可以解决问题.

编辑:如果你想使用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];
Run Code Online (Sandbox Code Playgroud)

另外,您可以使用以下事实:只需要调用void方法以使代码稍微简单一些.由于这不再使用匿名方法,您可以取消"内部"变量:

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