我一直认为MessageBoxes有点像断点 - 他们停止执行程序,直到用户点击" OK。"但是,我刚刚发现这是不准确的,我试图找出MessageBoxes何时会停止执行。
搜索SO(成功)解决问题的方法我发现了这个伪代码:
if (somethingHappened())
{
timer1.Enabled = false;
MessageBox.Show("something happened");
}
else continue with other stuff ...
表现与此不同:
if (somethingHappened())
{
MessageBox.Show("something happened");
timer1.Enabled = false;
}
else continue with other stuff ...
在第一种情况下,计时器停止并显示消息框。在第二种情况下,将显示消息框,但计时器不会停止。该计划只是继续其他的东西。显然,必须在计时器停止之前单击MessageBox,但我的程序才继续运行。 (再次调用事件处理程序,出现另一个MessageBox,并且它被卡在无限循环中。)
那么,在什么条件下,MessageBox 不是是真正的模态,在用户响应之前无法停止执行程序?
答案 0 :(得分:3)
MessageBox
永远不会停止执行程序。它只是停止执行调用它的代码序列。所以在这种情况下:
timer1.Enabled = false;
MessageBox.Show("something happened");
由于您将Enabled
设置为false
,计时器停止了。但在这种情况下:
MessageBox.Show("something happened");
timer1.Enabled = false;
计时器尚未停止,因为在您通过MessageBox
对话框后,您尚未将Enabled
设置为false
。命令式代码语句按照它们的写入顺序执行。第二行不会执行,直到第一行完成。
这与应用程序中的其他线程无关。只是调用MessageBox
。
答案 1 :(得分:3)
消息框是模态的。但是为了服务它的GUI,它运行所谓的模态消息循环。该消息循环拉取调度同步消息,并处理异步消息。像WM_TIMER
一样。而后一个事实意味着你的计时器继续开火。
你调用MessageBox.Show
,直到对话框关闭才真正返回。但是MessageBox.Show
内部是一个处理消息的循环。部分消息处理涉及调用计时器事件。由于非终止递归,很可能导致堆栈溢出。这正是发生在你身上的事情。
要点摆脱这一点的关键是MessageBox.Show
调度计时器事件(以及其他事件),这可能导致重新入侵。
答案 2 :(得分:0)
是的,MessageBox.Show()
是一个模态窗口,执行消息框的线程的执行被有效阻止继续,直到窗口关闭。因此,您的timer1.enabled
代码仅在关闭后执行,当然其他线程不受此影响并将继续执行,即使是代表计时器对象执行的代码。
没有非模态MessageBox.Show()
方法,如果您需要非模态行为,则必须编写自己的消息框表单。