GDI+多线程绘图

GDI+ drawing with multithreading

本文关键字:绘图 多线程 GDI+      更新时间:2023-10-16

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

我有一个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);
}

以及绘制&处理消息非常简单。它们每个都有一个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;
}

当我不使用线程并删除drawObject()中的"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:(

微软网站上PeekMessage的报价:

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

如果hWnd为NULL,PeekMessage将检索任何窗口的消息属于当前线程,并且当前线程上的任何消息线程的消息队列,其hwnd值为NULL(请参阅MSG结构)。因此,如果hWnd为NULL,则窗口消息和线程消息被处理。

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

我怀疑线程没有"当前窗口",而且"当前线程消息队列"并不是Windows实际将消息作为默认线程发布到的队列。这只是一个假设,因为你的方法完全有可能存在其他问题。但我认为这是问题所在的主要部分。