我有两个窗体。我使用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");
}
答案 0 :(得分:2)
这是因为事件在表单从屏幕上移除之前触发,MessageBox.Show(
阻塞,直到您按下确定按钮。
这是来自.NET框架的反编译源代码,用于处理表单关闭的私有函数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
的工作,一旦完成关闭它将在消息队列中查找更多工作要做然后显示消息框。