Search code examples
c++windowsmultithreadingwinapimessage-loop

Why does the win32 message loop stop working when threaded?


I am trying to create a WIN32 (C++) program in which I will have to simultaneously process messages and run a while loop. In order to do that, I want to use threads.

When I moved the message loop to a separate procedure (called from the function WinMain), all things were working fine. However, when I used the code below to thread that procedure, instead of simply calling it from the main process, the window becomes unresponsive.

Do you know why that happens?

Inside WinMain, after creating the main window, I removed the message loop and the return value, adding the following piece of code:

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

return_val is a global variable which I will use to receive the value WinMain should return when the message loop ends.

Also, the function message_loop is as follows:

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

Solution

  • The fundamental reason is that Windows has the notion of a thread message queue. Each thread has its own message queue. It's OK to run GetMessage in a thread, but it will get you only the messages that belong to that thread, such as for windows which you create in that thread. Messages belonging to any other thread (no matter how that other thread was created) will not be visible in your thread.

    As you state, your std::thread is created only "after creating the main window". That means you have two thread message queues; one from the main thread which created the main window, and another queue for your std::thread. The latter queue will remain empty.

    You see this in the second argument to GetMessage - passing HWND=0 there means "all messages for this thread".

    In theory, you can have multiple threads for multiple windows, but that quickly gets very complex. So in practice, the most common solution is to use the main thread, and the only reasonable alternative is to have a single dedicated thread.