【问题标题】:Is it possible to put custom message in win32 message queue in FIFO order?是否可以按 FIFO 顺序将自定义消息放入 win32 消息队列中?
【发布时间】: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


【解决方案1】:

假设答案是“否”(没有其他插入消息的方式)。 但是,在处理发布的消息时,我可以监视经过的时间,并立即通过 WM_TIMER 发出相同的消息而不是处理它。

更新

经过一些观察,似乎没有给定时间(1 毫秒?5 毫秒?)保证输入将被处理。相反,有效的是显式检查消息队列中的输入消息:

case MY_MSG:
{
    MSG msg;
    if(PeekMessage(&msg,0,0,0,PM_NOREMOVE|PM_QS_INPUT))
        SetTimer(hwnd,MY_TIMER,0,0);
    else
        DoWork();
}
return 0;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-09
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2016-04-29
    • 1970-01-01
    • 2021-09-10
    相关资源
    最近更新 更多