0

免责声明:在多线程方面,我有点菜鸟。我在网上阅读了一些东西,做了一些简单的多线程示例。

我有一个 Win32 应用程序,它想在一个线程中绘制内容并在另一个线程中处理 Win32 消息。但是,在创建窗口并启动线程后,它会挂起。我有一种预感,它可能与WaitForMultipleObjects()有关,但我不知道如何使它正确。有谁知道为什么会这样?我应该暂停和恢复线程吗?

这是我的代码:

WinAPI:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
    /* initialization blah blah */

    zgE->startThreads(); // <--- starts the 2 threads

    WaitForMultipleObjects(zgE->getThreadsNo(), zgE->getThreads(), TRUE, INFINITE);
    return TRUE;
}

这就是我启动线程的方式:

void zgEngine::startThreads()
{
    /* allocation and stuff, blah blah blah */

    m_arrThreads[m_nThreads++] = CreateThread(NULL, 0, &zgEngine::handleMsg, (void*)this, NULL, NULL);
    m_arrThreads[m_nThreads++] = CreateThread(NULL, 0, &zgEngine::drawObjects, (void*)this, NULL, NULL);

    assert(m_nThreads <= THREADS_NO);
}

绘制和处理消息的 2 个函数非常简单。它们每个都有一个while循环。

// draw function
DWORD WINAPI zgEngine::drawObjects(LPVOID lpParam)
{    
    while (true)
    {
        /* draw stuff - valid code that if called outside this function
           works as intended  */
    }

    return TRUE;
}

// message handler function
DWORD WINAPI zgEngine::handleMsg(LPVOID lpParam)
{
    MSG msg;
    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            // Process the message
            if (msg.message == WM_QUIT)
                break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return TRUE;
}

当我不使用线程并删除drawObjects()中的“while(true)”,但留下代码(只执行一次)时,不要调用handleMsg()并像下面的例子一样制作WinMain,它奇迹般有效。

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
    /* initialization blah blah */

    MSG msg;
    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            // Process the message
            if (msg.message == WM_QUIT)
                break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {
             zgEngine::DrawObjects(zgE);
        } 
    }
    return TRUE;
}

稍后编辑:据我所见, PeekMessage() 总是返回 0 :(

4

1 回答 1

2

引用自PeekMessage微软网站:

要检索其消息的窗口的句柄。窗口必须属于当前线程。

如果 hWnd 为 NULL,则 PeekMessage 检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中 hwnd 值为 NULL 的任何消息(参见 MSG 结构)。因此,如果 hWnd 为 NULL,则窗口消息和线程消息都会被处理。

如果 hWnd 为 -1,PeekMessage 仅检索当前线程的消息队列中 hwnd 值为 NULL 的消息,即 PostMessage(当 hWnd 参数为 NULL 时)或 PostThreadMessage 发布的线程消息。

我怀疑该线程没有“当前窗口”,并且“当前线程消息队列”不是 Windows 实际将消息作为默认线程发布到的那个。这只是一个假设,因为您的方法完全有可能存在其他问题(以及?)。但我相信这是问题所在的主要部分。

于 2013-07-16T13:10:18.600 回答