无法在非主线程中创建基于 Window 的应用程序

Cannot Create Window-based Application in Non-main Thread

在我的一个项目中,我需要在非主线程中创建一个 window。我从来没有这样做过,所以我没有太多经验。

根据MSDN documentation and the SO question,我应该可以在其他线程中创建一个window,但我无法成功。即使在线程启动例程中,我注册了一个 window class,创建了一个 window 并提供了一个消息循环,线程启动并立即退出。此外,我无法调试线程启动例程,因此无法在其中设置断点。

有什么我想念的吗?我希望我不会错过任何愚蠢的事情。

请考虑以下演示。感谢您抽出宝贵时间。

#include <Windows.h>
#include <tchar.h>

HANDLE hThread;
DWORD WINAPI OtherUIThreadFunc(LPVOID args);

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

HWND m_hwnd;
MSG msg;
WNDCLASSEX m_wcx;
const int MESSAGE_PROCESSED = 0;
const TCHAR* m_szClassName = _T("DemoWndCls");
const TCHAR* m_szWindowTitle = _T("Demo Window");

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
{
    hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)OtherUIThreadFunc, hInstance, 0, NULL);
    /*MSG msg;

    ZeroMemory(&m_wcx, sizeof(m_wcx));
    m_wcx.cbSize = sizeof(m_wcx);
    m_wcx.style = CS_VREDRAW | CS_HREDRAW;
    m_wcx.hInstance = hInstance;
    m_wcx.lpszClassName = m_szClassName;
    m_wcx.lpfnWndProc = WndProc;
    m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    m_wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;

    if (!RegisterClassEx(&m_wcx))
        return false;

    m_hwnd = CreateWindowEx(0, m_wcx.lpszClassName, m_szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 360, NULL, NULL, hInstance, NULL);

    if (!m_hwnd)
        return false;
    ShowWindow(m_hwnd, SW_NORMAL);
    UpdateWindow(m_hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;*/
}

DWORD WINAPI OtherUIThreadFunc(LPVOID args)
{
    HINSTANCE hInstance = (HINSTANCE)args;

    ZeroMemory(&m_wcx, sizeof(m_wcx));
    m_wcx.cbSize = sizeof(m_wcx);
    m_wcx.style = CS_VREDRAW | CS_HREDRAW;
    m_wcx.hInstance = hInstance;
    m_wcx.lpszClassName = m_szClassName;
    m_wcx.lpfnWndProc = WndProc;
    m_wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    m_wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    m_wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;
    
    if (!RegisterClassEx(&m_wcx))
        return false;
    m_hwnd = CreateWindowEx(0, m_wcx.lpszClassName, m_szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 360, NULL, NULL, hInstance, NULL);
    if (!m_hwnd)
        return false;
    ShowWindow(m_hwnd, SW_NORMAL);
    UpdateWindow(m_hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        return MESSAGE_PROCESSED;
    case WM_DESTROY:
        PostQuitMessage(0);
        return MESSAGE_PROCESSED;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    
}

Window创建成功(理论上,反正)。问题是主线程将一个移动到 return,这导致运行时终止进程。

要解决此问题,您必须保持主线程处于活动状态。调用 WaitForSingleObject 或消息循环都是可能的选择。


这主要是遵循 C 和 C++ 约定的结果。在任何一种情况下,从 main 函数调用 return 都等同于调用 exit() 函数。这解释了为什么从主线程 returning 会破坏整个过程。

阅读奖励:If you return from the main thread, does the process exit?