消息循环是否在 UI 线程上执行?

vie*_*uoc 5 c# messages message-queue winforms

我对 winforms 中的消息循环如何工作感到非常困惑。我正在处理 Windows 表单,我知道何时调用Application.Run(myform),因此它将创建一个消息队列和消息循环,然后显示我的表单并开始在消息队列中检索消息以进行调度。

我阅读了一些主题,但仍然不明白消息循环在幕后如何工作,UI 线程同时运行消息泵和执行代码?以及消息循环如何使用线程?

我的问题是:消息循环是否会在 UI 线程上运行。如果是,为什么它不阻塞 UI 线程?

如果问题不清楚,请告诉我,对不起,因为我的英语不好。

ang*_*son 5

可以使用以下示例代码广泛地解释消息循环:

Message message;
while (PeekMessage(out message))
    ProcessMessage(messae);
Run Code Online (Sandbox Code Playgroud)

是的,这“阻塞”了线程。该线程将始终等待消息出现(PeekMessage 应在消息准备好时返回)或处理该消息。

重要的是要知道,是不会阻塞 UI 的魔法。UI 需要响应的任何内容都作为消息处理。

非常重要的部分是,为了避免阻塞UI,无论ProcessMessage的不处理单个消息不应该花费太长的时间

如果用户单击按钮,这将作为消息处理。作为处理该消息的一部分,您的事件处理程序将被调用。如果该事件处理程序开始做一些冗长的事情,您不会返回到消息循环,因此它会在您的按钮单击事件处理程序运行时停止处理消息。

所以是的,消息循环在 UI 线程上运行。是的,它也会阻塞 UI线程,但它继续运行的事实意味着它不会阻塞UI


受到评论的启发,我认为我应该发布一个类比来解释循环的工作原理。

想想当地的熟食店供应食物。有些食物是现成的,只需要卖给消费者,而有些食物则需要按需准备。

这家Deli有几种典型的操作:

  1. 必须接受食物订单
  2. 必须准备食物或取来食物
  3. 食物必须提供给消费者

现在,考虑一个桌子后面只有一个人的熟食店。

这个人为每个消费者做这三个操作。显然,如果一名消费者订购了必须在当时和那里准备好的食物,其他消费者将不得不等待。

另一方面,如果可以将这些订单交给厨师(接单员工的同事),那么接单的速度就会快得多。

在 Windows 中,消息循环就是这个接受订单的员工,而且只有他。

作为处理订单(消息)的一部分,这个人将不得不去检查其他人,然后等待,然后再将食物(结果)送回给消费者。因此,任何冗长的处理都会减慢该队列的处理速度。

另一方面,如果那个“其他人”只是说,你回到队列并告诉消费者他会在食物准备好后拿到食物,那么队列就会移动,即使现在有人正在等待他们的食物

这是为了保持 UI 响应而引入的典型线程或异步处理。