我对winforms中的消息循环如何工作非常困惑。我正在处理Windows窗体,我知道在调用Application.Run(myform)
时,它将创建一个消息队列和消息循环,然后显示我的窗体并开始在消息队列中检索消息以进行调度。
我阅读了一些主题,但仍然不了解消息循环如何在幕后工作,UI Thread both running message pump AND executing code?和How does the message loop use threads?
我的问题是:消息循环是否会在UI线程上运行。如果是,为什么它不阻止UI线程?
如果问题不明确请告诉我,对不起,因为我的英语不好。
答案 0 :(得分:3)
使用此示例代码可以广泛地解释消息循环:
Message message;
while (PeekMessage(out message))
ProcessMessage(messae);
是的,这个"阻止"线程。线程将始终等待消息出现(PeekMessage应在消息准备好时返回)或处理消息。
重要的是要知道这个是不会阻止UI的魔力。 UI需要响应的任何内容都将作为消息处理。
非常重要的一点是,为了避免阻止用户界面,无论ProcessMessage处理单个消息,都不应该花费太长时间。
如果用户点击按钮,则会将其作为消息处理。作为处理该消息的一部分,将调用您的事件处理程序。如果该事件处理程序开始执行冗长的操作,则您不会返回到消息循环,因此它会在您的按钮单击事件处理程序运行时停止处理消息。
所以是的,消息循环在UI线程上运行。是的,它还会阻止UI 线程,但它继续运行的事实意味着它不会阻止 UI 。
受到评论的启发,我认为我应该发布一个类比,解释为什么循环有效。
想想当地的熟食店。有些食物是现成的,只需要卖给消费者,有些食物必须按要求准备。
这款熟食店有几个典型的操作:
现在,考虑在桌子后面只有一个人的熟食店。
此人为每位消费者执行以下三项操作。显然,如果一个消费者订购的食品必须随时准备,其余消费者将不得不等待。
另一方面,如果这些订单可以发给一名厨师,一名接受订单的员工的同事,那么订单将会更快。
在Windows中,消息循环是此订单接受员工,只有他。
作为处理订单(消息)的一部分,这个人必须先检查别人,然后等待,然后再将食物(结果)带回消费者手中。任何冗长的处理都会减慢此队列的处理速度。
另一方面,如果那个"其他人"简单地说,你回到队列并告诉消费者他准备好后会得到食物,然后队列将会移动,即使有人正在等待他们的食物。
这是为了保持UI响应而引入的典型线程或异步处理。
答案 1 :(得分:0)
消息循环是否在UI线程上运行?
是。确实如此。
如果是,为什么它不阻止UI线程?
您应该看到消息循环为无限循环:它会一直运行。每当队列中有一条消息要处理时,它就会拾取并执行它。这可以是单击的按钮。那时按钮会被通知有关事件,它将运行与之关联的代码,例如您的button_Click
事件处理程序。如果您将Thread.Sleep(10000)
放入其中,您会发现它将在该睡眠期间(10秒)阻止整个应用程序。您无法调整大小,重绘或执行任何其他操作,因为消息循环也会被阻止。事件处理程序结束后,它将继续从队列中获取下一条消息。