堆栈溢出异常关闭表单。

4
我在WinForms中遇到了问题。我创建了一个MDIParent-Form并在MDIParent的Load事件中调用ChildForm。我希望当ChildForm关闭时,MDIParent也会关闭并退出应用程序。因此,我在MDIParent中为ChildForm编写了一个事件,以便在ChildForm关闭时,MDIParent将触发FormClosed事件。但是它抛出了一个堆栈溢出异常。我知道这是一个无限循环,但我不知道原因...
   private void MDIParent1_Load(object sender, EventArgs e)
    {
        Form1 childForm = new Form1();
        childForm.MdiParent = this;
        childForm.FormClosed += childForm_FormClosed;
        childForm.Show();
    }

    void childForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        this.Close(); 
        //{Cannot evaluate expression because the current thread is in a stack overflow state.}
    }

但是如果我使用

  Application.Exit();

使用 this.Close() 时出现问题,但如果使用其他方式就可以正常工作。我想知道为什么,请问有人能解释一下吗?

更新:我在没有 MDIParent 的情况下尝试了相同的操作,一切都正常了...但为什么使用 MDIParent 就会出现问题呢?


4
你有一个无限循环:如果表单被任何事件关闭,它将告诉表单关闭,这将再次触发该事件并尝试再次关闭。 - Mephy
如果我不使用MDIParent,为什么它能工作? - Issa Jaber
1
也许当您调用 this.Close() 时,它会在所有子窗体上调用 close,从而调用 childForm_FormClosed,这就是您的无限递归吗?我几乎可以确定 Memphy 的解释是正确的。 - MariusUt
2
如果你关闭父级,子级也会被关闭吗?这可能会解释你的无限循环。 - Patrick
1个回答

5

这是一个小bug,问题在于当FormClosed事件触发时,子窗体仍然存在于MDIParent1.MdiChildren集合中。换句话说,FormClosed事件触发得有点太早了。因此,当您关闭父窗体时,它会再次尝试关闭子窗体,从而再次触发子窗体的FormClosed事件,进而再次关闭父窗体,循环重复。事件触发顺序永远都是个问题,那么我们称其为一个bug。

解决方法是使用Disposed事件,该事件稍晚触发:

private void MDIParent1_Load(object sender, EventArgs e)
{
    Form1 childForm = new Form1();
    childForm.MdiParent = this;
    childForm.Disposed += childForm_Disposed;
    childForm.Show();
}

void childForm_Disposed(object sender, EventArgs e)
{
    this.Close();   // Fine now
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接