为什么在线程化时win32消息循环停止工作?

问题描述

我试图创建一个WIN32(C ++)程序,在该程序中我必须同时处理消息并运行while循环。为此,我想使用线程。

当我将消息循环移到一个单独的过程(从WinMain函数调用)时,一切正常。但是,当我使用下面的代码对该过程进行线程化时,而不是简单地从主进程中调用它,该窗口将变得无响应。

你知道为什么会这样吗?

在WinMain内部,创建主窗口后,我删除了消息循环和返回值,并添加了以下代码

std::thread t1(message_loop);
t1.join();
return return_val;

return_val一个全局变量,当消息循环结束时,我将使用它来接收WinMain应该返回的值。

此外,函数message_loop如下:

void message_loop()
{
    MSG messages;
    while (GetMessage (&messages,NULL,0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        dispatchMessage(&messages);
    }
    return_val = messages.wParam;
}

解决方法

根本原因是Windows具有线程消息队列的概念。每个线程都有自己的消息队列。在线程中运行GetMessage是可以的,但是只会获得属于该线程的消息,例如在该线程中创建的窗口的消息。属于任何其他线程的消息(无论如何创建该其他线程)在您的线程中都不可见。

如您所述,std::thread仅在“创建主窗口之后”创建。这意味着您有两个线程消息队列。一个来自创建主窗口的主线程,另一个用于std::thread的队列。后一个队列将保持为空。

您在GetMessage的第二个参数中看到了这一点-在此处传递HWND=0表示“此线程的所有消息”。

理论上,您可以为多个窗口使用多个线程,但是很快就会变得非常复杂。因此,实际上,最常见的解决方案是使用main线程,而唯一合理的选择是只有一个专用线程。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...