【问题标题】:Windows: two threads handling messages?Windows:两个线程处理消息?
【发布时间】:2012-01-13 10:51:44
【问题描述】:

我希望有两个线程来处理 Windows 消息。一个用于客户端区域中的键/鼠标输入(该线程还负责游戏逻辑),另一个用于其余的,因为我正在制作游戏并且某些消息导致 DefWindowProc() 阻塞(从而冻结游戏)。

我怎样才能做到这一点?

【问题讨论】:

  • DefWindowProc 并没有真正“阻止”......它非常快。你能举一个导致阻塞的示例消息吗?
  • 最好保留现有设计,而是在后台线程上运行缓慢的响应以避免游戏冻结。
  • 如果您正在移动或调整窗口大小,DefWindowProc 会阻塞,直到您释放鼠标按钮
  • 您可以执行一个简单的测试,看看这是否真的如此。使用 SetTimer 创建一个计时器,然后处理 WM_TIMER 消息。尝试调整窗口大小,看看您是否停止接收消息。你应该会发现你仍然得到它们。
  • 有一些多人游戏的工作经验 - 如果游戏在用户尝试移动/调整窗口大小时冻结有什么大不了的?只要游戏时钟跟上下一个渲染帧的实际时间,您应该能够处理这个问题。只需将其视为系统“打嗝”(无论如何都会不可避免地发生)。在激烈的游戏过程中,用户会很快发现不要弄乱窗口。

标签: c winapi


【解决方案1】:

与 Cody 所写的相反,您绝对可以处理来自多个线程的消息。但是,这不是可定制的免费供所有人使用。相反,窗口具有线程关联性:每个线程将接收发送或发布到由该线程创建的窗口的消息。无法将任何窗口的消息传递到任何其他线程。

对于您的特殊情况,为什么不创建一个带有自己的隐藏窗口和消息循环的工作线程?每当主窗口收到您不想在主线程中处理的消息时,将其发布到另一个窗口,它将排队到工作线程并由工作线程处理。

【讨论】:

  • 啊,我并没有暗示任何不同的意思。也许我夸大了一点。我看到这里有太多人在尝试在非 UI 线程上进行 UI 工作时遇到了很大的麻烦。
【解决方案2】:

您应该只需要一个线程来处理消息队列,这是 Windows 已经提供的。如果你正在做任何计算量很大的事情,你应该通过使用 CreateThread 创建一个新线程来将它分派到一个单独的线程。如果你发现你经常这样做,那么让那个线程永久存在,但在你需要的时候发出信号让它工作。

【讨论】:

    【解决方案3】:

    不,所有消息都需要在单个线程上处理。这个单线程通常被称为 UI 线程,因为它是控制用户界面的线程。尝试在非 UI 线程上处理 UI 消息只会给您带来麻烦。

    但是,一个常见问题是应用程序执行长时间运行的计算密集型任务以响应特定消息。这效果不好,因为当代码在消息处理程序中运行时,应用程序无法处理 other 消息(线程一次只能做一件事),并且您的 UI 变成没有反应。

    解决方案是分拆另一个线程(或两个或多个您需要的线程)并将长时间运行的计算密集型任务委托给该线程。您仍将在单个 UI 线程上处理消息,但在消息处理程序内部是将任务传递给辅助线程的地方。您会经常听到这被称为“工作线程”或“后台线程”模式。

    您可以使用CreateThread function 创建其他线程。您可以找到示例here

    在这种情况下,听起来QueueUserWorkItem function 可能是一个更简单的选项。示例代码:

    DWORD CALLBACK ThreadProc(LPVOID p)
    {
        HWND hWnd = reinterpret_cast<HWND>(p);
    
        for (int i = 0; i < 100000; ++i)
        {
            // do whatever
        }
    
        return 0;
    }
    
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_KEYDOWN: // or whatever message you want to respond to
            {
                QueueUserWorkItem(ThreadProc, hWnd, WT_EXECUTELONGFUNCTION);
                return 0;
            }
            // process other messages...
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    

    Win32 线程池的必读是here

    【讨论】:

    • 您可以拥有多个 UI 线程,但是每个窗口只与一个线程相关联,其消息将被传递到该线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多