Form.Close()不会立即关闭窗口

时间:2011-08-18 07:03:22

标签: c# winforms

如果用户以某种方式关闭主窗体,我需要确保所有窗体都将关闭。所以我决定隐藏Close()函数,我写了这样的东西

public new bool Close()
        {
            List<Form> formsList = new List<Form>(Application.OpenForms.Count);
            foreach (var form in Application.OpenForms)
                formsList.Add((Form)form);
            formsList.Reverse();
            foreach (var form in formsList)
            {
                if (form.IsDisposed) continue;
                Invoke(new GenericEventHandler(() => { form.Close(); }));
            }

            return Application.OpenForms.Count == 0;
        }

因此,如果所有表单都已成功关闭,我将返回true,并且由于这一点,我知道用户可以从应用程序注销。

然而,似乎不会立即触发form.Close()函数。调用form.Close()后,不立即触发formclosed事件以及集合Application.OpenForms未被修改。已更改已打开表单的数量。

可能是什么原因?

5 个答案:

答案 0 :(得分:5)

为什么不使用

Application.Exit();

答案 1 :(得分:1)

如果主窗体是通过Application.Run(new MainForm());在WinForms中以标准方式创建的,那么当它关闭时,应用程序将退出,关闭所有其他窗体。因此,我认为您不必担心手动关闭所有子表单。

答案 2 :(得分:1)

好吧,如果用户关闭了主表单,那么一旦关闭它,您的应用程序肯定会退出,因为您的表单负责在应用程序传递给Application.Run()时保持应用程序处于活动状态

现在,如果您想在关闭 表单时关闭应用,请执行以下操作:

protected override void OnFormClosed(FormClosedEventArgs e)
{
    base.OnFormClosed(e);
    Application.Exit();
}

答案 3 :(得分:0)

一般情况下,我建议不要对Control和/或Form类的任何成员使用new关键字。如果您需要自己的方法,请使用自己的名称。

在代码中,关闭子表单时不需要使用Invoke。

如果您需要确保在实际执行与MainForm.Close相关的逻辑之前关闭了所有子窗体,您可以使用类似于下面的处理程序订阅MainForm.FormClosing事件:

void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    bool allChildFormsClosed = !closeAllChildForms();

    if(!allChildFormsClosed)
    {
        e.Cancel = true;
        MessageBox.Show("Failed to close one or more child forms.");
        // better add some yes|no dialog to force exit if necessary
    }
}

您可以用与上面类似的方式实现closeAllChildForms - 只需:删除formsList.Reverse();和'Invoke ..' - 直接调用Close并更新:if(this == form || form.IsDisposed)continue;

答案 4 :(得分:0)

如果由于某种原因,Application.Exit没有为您剪切,您可以尝试此代码(将其放在表单的FormClosing事件中):

while (Application.OpenForms.Count > 1)
{
  Form form = Application.OpenForms[1];
  form.Close();
  while (!form.IsDisposed) Application.DoEvents();
}

或者如果你想让它在一段时间后无法关闭所有表格时超时,

while (Application.OpenForms.Count > 1)
{
  Form form = Application.OpenForms[1];
  form.Close();
  DateTime StartTime = DateTime.Now;
  while (!form.IsDisposed && (StartTime - DateTime.Now).TotalMilliseconds < 1000)
    Application.DoEvents(); //1-second timeout here
  if (!form.IsDisposed) //if it's still not closed
  {
    //send a message to the user that the application can't exit right now
    mbox("some forms are still open or whatever");
    e.Cancel = true;
    return;
  }
}