c# - 为什么Form.Close要等待MessageBox.Show?

标签 c# winforms synchronization begininvoke invokerequired

请看这个:

var form = new Form();

form.Shown += (_, __) =>
{
    var timer = new System.Windows.Forms.Timer { Interval = 1000 };

    timer.Tick += (x, xx) =>
    {
        timer.Stop();
        GC.KeepAlive(timer);
        timer.Dispose();

        form.Close();

        Application.DoEvents(); // no effect 

        // it will cause form keep show
        MessageBox.Show("asdf");

        // but if this, that's fine
        // BeginInvoke(new Action(() => MessageBox.Show("asdf")));
    };

    timer.Start();
};

form.ShowDialog();

form.CloseMessageBox.Show 之前,但 form 在关闭 msgBox 之前不会关闭,请帮忙。

--结束--

一切都在代码中,为什么需要更多的文字?一切都在代码中,为什么需要更多的文字?一切都在代码中,为什么需要更多的文字?

最佳答案

当您使用 ShowDialog() 将表单显示为模式时,调用 Close 实际上会发送一条 WM_CLOSE 消息,然后设置 DialogResultCancel 充当模态消息循环退出循环的标志。

因此Close不会立即关闭或隐藏模式对话框。然后,在完成模态消息循环后,模态对话框将被隐藏(但不会被销毁)。

MessageBox 方法也会阻止代码的执行,因此消息框之后的代码将在关闭消息框后立即执行。现在很清楚为什么在调用Close之后,首先显示MessageBox,然后在关闭消息框后,表单关闭。

为了更容易理解,这里有一个伪代码,它显示了当您在代码中调用 ShowDialog 时发生的情况:

Form Shows
While Form.DialogResult != None
{
    Form.Close → Sends WM_CLOSE → Sets Form.DialogResult = Cancel 
    MessageBox.Show and wait until MessageBox closes
}
Form Hides

请记住,Close 不等于return,这意味着Close 后的代码也将运行。这里的代码是 MessageBox ,它会阻塞循环,直到 MessageBox 关闭。

要立即隐藏对话框,请将 form.Close() 替换为 form.Hide(),这样无需等待循环,您就可以命令表单隐藏起来。但这并不意味着 form 已关闭,因此 ShowDialog 之后的代码行直到循环结束后才会运行。

有关 CloseShowDialog 如何工作的更多信息,您可能需要查看 Windows 窗体源代码,特别是以下几行:

关于c# - 为什么Form.Close要等待MessageBox.Show?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57336299/

相关文章:

c# - 如何将 DropDownList 包装在 GridView FooterTemplate 中?

c# - 惊讶地发现 C# 编译器可以推断出信息较少的声明

C# - 获取通用列表的项目类型

c# - LinearGradientBrush 无法正确呈现

javascript - 后台同步未在 serviceworker 中触发事件

c - 生产者消费者示例中的信号量同步出错

c# - 对已实例化的对象使用 using 语句

c# - Winforms 图形闪烁。 (双缓冲没有帮助!)

c# - 如何从 json 对象循环遍历某个 token?

java - Java 如何管理对数组元素的多线程访问?