【问题标题】:form not closing immediately after listening to FormClosed event收听 FormClosed 事件后表单未立即关闭
【发布时间】:2014-02-12 14:12:21
【问题描述】:

我有两个窗体。我使用 Form.Show() 通过单击第一个表单的按钮调用第二个表单。我想在表单关闭后显示一个消息框。我订阅了 FormClosed 事件,但表单仅在显示消息框后关闭。

发生这种情况的任何原因?

private void button1_Click(object sender, EventArgs e)
{
    Form2 fr2 = new Form2();
    fr2.FormClosed += new FormClosedEventHandler(fr2_FormClosed);
    fr2.Show(); 
}  

void fr2_FormClosed(object sender, FormClosedEventArgs e)
{
    MessageBox.Show("second form closed");
}

【问题讨论】:

  • 在你的代码 sn-p 中你订阅了FormClosing 事件而不是FormClosed
  • 那是错字..我尝试了这两个事件 :) 现在更正了

标签: c# winforms events


【解决方案1】:

发生这种情况是因为该事件在表单从屏幕上移除之前触发,MessageBox.Show( 会阻塞,直到您按下确定按钮。

这是处理关闭表单的私有函数WmClose 的反编译源代码。

private void WmClose(ref Message m)
{
      //Snip...

      FormClosedEventArgs e3 = new FormClosedEventArgs(this.CloseReason);
      this.OnClosed((EventArgs) e3);
      this.OnFormClosed(e3);
      base.Dispose();
}

protected virtual void OnFormClosed(FormClosedEventArgs e)
{
  Application.OpenFormsInternalRemove(this);
  FormClosedEventHandler closedEventHandler = (FormClosedEventHandler) this.Events[Form.EVENT_FORMCLOSED];
  if (closedEventHandler == null)
    return;
  closedEventHandler((object) this, e); //This line is what calls fr2_FormClosed
}

在调用base.Dispose() 之前,该表单仍然在屏幕上可见,并且代码不会从this.OnFormClosed(e3); 返回,直到您的代码从fr2_FormClosed 返回。

最简单的解决方法是通过 BeginInvoke( 将消息框放在消息队列中来推迟消息框的显示

void fr2_FormClosed(object sender, FormClosedEventArgs e)
{
    this.BeginInvoke(new Action(() =>
    {
        MessageBox.Show("second form closed");
    }));
}

现在这会将显示消息框的操作放到消息泵队列中,并继续关闭Form2,一旦完成关闭,它将在消息队列上寻找更多工作,然后显示消息框。

【讨论】:

    猜你喜欢
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 2012-12-03
    • 2023-04-11
    • 1970-01-01
    • 2017-09-26
    • 2012-05-13
    相关资源
    最近更新 更多