【发布时间】:2019-04-21 04:32:09
【问题描述】:
有几种方法可以为 GUI 线程添加消息。
PostMessage:根据文档,首先处理这些消息(在大多数其他消息之前)。如果我经常使用它,GUI 线程可能会卡在只处理我的消息而不是其他任何东西(不会响应键盘\鼠标等)。这种方法的优先级太高了。
SetTimer:WM_TIMER 消息在其他所有操作之后最后处理,因此如果发生任何绘画(例如,如果我连续移动窗口),所有时间都将用于处理常见消息,并且 WM_TIMER 将触发太晚了。 这种方法的优先级太低了。
我需要一些中间的东西来尽快处理我的自定义消息,但仍然为其余消息留出空间以保持 GUI 响应。
我想尝试将一些消息按照与普通消息相同的顺序进行处理。 那么问题来了,我该怎么做呢?
添加:
我有一个准备视频帧的线程,它需要通知主 (UI) 线程新帧已准备好并可能显示它。在典型的游戏循环中,它类似于
- 处理消息直到队列为空
- 处理 1 帧
- 重复
但现在我无法控制消息循环,因为它可能在模式弹出窗口或菜单中。
【问题讨论】:
-
与“普通消息”相同的顺序是
PostMessage。如果您不仅讨论可能的解决方案,而且告诉我们问题/您想要实现的目标,那将会有所帮助。 -
没有“中间”。发布的消息按队列顺序处理。如果存在您过于频繁地调用 PostMessage() 的风险,那么您的 UI 线程就有可能会烧毁 100% 内核。必须始终避免这种情况。绘画也是“低优先级”,所以至少绘画会抓住。你注意到了。除了 WM_MOUSEMOVE 之外,鼠标/键盘消息不是。
-
添加了描述。也许我的理解是错误的?这里它说:docs.microsoft.com/en-us/windows/desktop/api/winuser/… 消息按以下顺序处理:已发送消息;已发布消息;输入(硬件)消息和系统内部事件;发送消息(再次); WM_PAINT 消息; WM_TIMER 消息;事实是,一旦我发布消息的速度略快于它们的处理速度,UI 就会卡住(没有处理一条鼠标消息)。
-
如果您有不同的消息循环(例如模式对话框或菜单),则视频可能应该暂停。另一种方法是使用 WM_ENTERIDLE,它在消息循环被清空时由模式对话框或弹出菜单的所有者接收。如果你走那条路,你会检查 WM_ENTERIDLE 中的新框架标志(除了你现在做的任何地方)并在指示新框架时使窗口无效。
-
多年前我们从头开始制作了一个生产游戏引擎,我们的策略是结合一个面向游戏的 MsgWaitForMultiple 对象样式循环,当一个模式启动时,用一个 ~10fps 的基于 SetTimer 的循环来补充它。所以当游戏在前台时我们会以大约 120fps 的速度进行渲染,如果有一个模式,或者应用程序不在前台,我们会以 10fps 的速度进行渲染。如果您真的想要高性能但消耗能量,那么在 QueryPerformanceCounter 上执行一个繁忙的等待循环,仅在没有时间渲染下一帧时执行 peek-message 轮询(再次使用基于 WM_TIMER 的模态回退)
标签: winapi