我对这个简单的任务感到困惑,我一遍又一遍地做。
我有一系列子表单。该数组在另一个表单的构造函数中启动:
frmChildren = new ChildGUI[20];
当用户请求查看子表单时,我这样做:
if (frmChildren[nb] == null)
{
frmChildren[nb] = new ChildGUI();
frmChildren[nb].MdiParent = this.MdiParent;
}
frmChildren[nb].Show();
到目前为止,此有效。在后台我可以下载这些表单的新内容。下载完成后,我将触发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];
我在.Close()上遇到了Cross Thread异常。注意我已经尝试过调用,但这样做会因某种原因绕过!= null。我认为它可能与垃圾收集器有关。有人有输入吗?
答案 0 :(得分:9)
问题是您的匿名方法正在捕获i
- 所以当它在UI线程中实际调用时,您有i
的不同值,可能为空。试试这个:
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];
除此之外,您可以使用以下事实:您只需要调用void方法以使代码稍微简单一些。由于这不再使用匿名方法,您可以取消“内部”变量:
foreach (ChildGUI control in frmChildren)
{
if (control != null)
{
control.BeginInvoke(new MethodInvoker(control.Close));
}
}
frmChildren = new ChildGUI[20];