【问题标题】:Question about message loop关于消息循环的问题
【发布时间】:2011-05-08 07:23:34
【问题描述】:

有个问题困扰了我很久。

短版:

Windows 消息循环的工作模式是什么?

详细版本:

当我们启动一个 Windows 应用程序(不是控制台应用程序)时,我们可以通过鼠标或键盘与它进行交互。应用程序从它的消息队列中检索代表我们运动的各种消息。 Windows 负责收集我们的操作并将消息正确地输入此队列。但这种情况不是意味着 Windows 必须无限式地运行吗?

我认为 Windows 调度程序 应该一直在运行。它可能会在预定义的时间间隔被时间中断调用。当调度器被时间中断触发时,它将当前线程切换到下一个待处理线程。单个线程只有在计划运行时才能通过GetMessage() 获取其消息。

我想知道如果只有一个 Windows 应用程序在运行,这个应用程序会不会有更多机会收到它的消息?

更新 - 1(2010 年 11 月 22 日上午 9:59)

这是我的最新发现:

根据 Chapter 7 Section: Thread Priorities

...例如,如果您的进程' 主线程调用 GetMessage() 和 系统发现没有消息 待定,系统暂停您的 porcess 的线程,放弃 线程时间片的剩余部分, 并立即将 CPU 分配给 另一个等待线程。

如果 GetMessage 没有消息显示 检索,进程的主要 线程保持挂起,永远不会 分配给一个 CPU。然而,当一个 消息被放置在线程的 排队,系统知道 线程不应再被挂起 如果没有,则将线程分配给 CPU 更高优先级的线程需要 执行。

我目前的理解是:

为了让系统知道何时将消息放入线程的队列中,我可以想到两种可能的方法:

1 - 集中式方法:系统负责始终检查每个线程的队列。甚至该线程也因缺少消息而被阻止。如果有任何消息可用,系统会将该线程的状态更改为可调度。但在我看来,这种检查可能会给系统带来真正的负担

2 - 分布式方法:系统不会检查每个线程的队列。当线程调用GetMessage,发现没有消息可用时,系统只会将该线程的状态改为阻塞状态,不再可调度。并且将来无论谁将消息放入阻塞线程的队列中,都是这个“”(不是系统)负责将线程的状态从阻塞ready (或任何状态)。 所以这个线程被系统取消了调度的资格,并被其他人重新获得了GetMessage的资格。系统关心的只是调度 runable 线程。系统并不关心这些可调度线程来自哪里。这种方法将避免方法一的负担,从而避免可能的瓶颈。

其实这里的重点是,线程的状态是怎么变化的?我不确定它是否真的是一个 分布式范式,如方法 2 所示,但它会是一个不错的选择吗?

【问题讨论】:

  • 我想开始赏金,但我还看不到开始赏金按钮。
  • 如果有版主可以帮助我开始赏金,请这样做。谢谢。
  • 您看不到“开始赏金”按钮,因为您已经打开了赏金。 (见这里:meta.stackexchange.com/questions/56703/…

标签: windows multithreading operating-system


【解决方案1】:

我想知道是否只有一个 Windows 应用程序正在运行,这会 应用程序有更多机会获得它 留言?

是的,可能,但我认为你可能错过了一个关键点。从队列中提取消息是一个阻塞调用。使用的数据结构通常称为阻塞队列。出队操作旨在在队列为空时自愿让出当前线程的执行。线程可以使用各种不同的方法保持停止,但在这种情况下,线程很可能使用内核级机制保持在等待状态。一旦给出队列有可用项目的信号,线程可能会进入就绪状态,调度程序将开始分配其公平的 CPU 份额。换句话说,如果该应用程序没有待处理的消息,那么它只是处于空闲状态,消耗接近于零的 CPU 时间。

【讨论】:

  • 感谢您的帖子。我已将我的评论添加到 Ringding 的回复中。我很好奇阻塞队列是如何实现的? 在我看来,即使有阻塞队列,也必须有人始终监控队列。否则,谁知道有什么东西入队了?这不是意味着某种繁忙的轮询吗?
  • 你肯定问对了问题。老实说,我不知道内核级别的阻塞机制是如何工作的。但是,如果我要在应用程序级别创建一个阻塞设备,我会结合使用慢轮询技术和一个 API,该 API 会导致线程产生其时间片。轮询将足够频繁以在几毫秒内做出响应,但足够慢以消耗接近零的 CPU 时间。同样,内核级机制可能使用完全不同的策略。知道它是什么会很有趣吧?
【解决方案2】:

应用程序在其消息循环中调用GetMessage()。如果消息队列为空,则该进程将阻塞,直到另一条消息可用。因此,GetMessage 是一种进程告诉 Windows 它目前无事可做的方式。

【讨论】:

  • 感谢您的回复。那么“块”逻辑是如何实现的呢?我想知道正在执行 GetMessage() 的线程是否只是忙于循环轮询消息,直到它被操作系统安排走?
  • 补充一点:这是某种自旋锁吗?
  • @smwikipedia:它被安排走了。操作系统内核有多种阻塞方法,只有当锁在很短的时间内被释放时才会使用自旋锁,这对 GetMessage 来说没有意义,因为它可能需要几分钟或几小时才能到达特定进程的下一条消息.
【解决方案3】:

您运行的线程越少(时间片被安排给线程,而不是进程),任何单个应用程序从其队列中提取消息的机会就越大。实际上,这与 Windows 消息无关;所有多线程都是如此;运行的相同或更高优先级的线程越多,任何线程获得的时间片就越少。

除此之外,我不确定您真正要问的是什么...

【讨论】:

  • 感谢您的回复。我稍后会细化我的问题。
猜你喜欢
  • 1970-01-01
  • 2014-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多