简体   繁体   English

GDI +使用多线程绘图

[英]GDI+ drawing with multithreading

Disclaimer: I'm somewhat of a noob when it comes to multi-threading. 免责声明:在涉及多线程时,我有点像菜鸟。 I've read stuff online, have done some simple multi-threading examples. 我在线阅读了一些内容,做了一些简单的多线程示例。

I've got a Win32 app that wants to draw the stuff in one thread and handle the Win32 messages in another thread. 我有一个Win32应用程序想要在一个线程中绘制东西并在另一个线程中处理Win32消息。 However, after the windows is created and the threads start, it hangs. 但是,在创建窗口并且线程启动后,它会挂起。 I have a hunch that it may have to do with WaitForMultipleObjects() , but I don't know how to make it right. 我有一种预感,它可能与WaitForMultipleObjects()有关 ,但我不知道如何使它正确。 Does anyone have any idea why this is happening? 有谁知道为什么会这样? Should I suspend and resume threads? 我应该暂停和恢复线程吗?

Here's my code: 这是我的代码:

WinAPI: 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;
}

This is how I start the threads: 这是我启动线程的方式:

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);
}

And the 2 functions that draw & handle messages are quite simplist. 绘制和处理消息的2个函数非常简单。 A while loop in each of them. 每个人都有一个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;
}

When I don't use threads and remove the "while (true)" in drawObjects(), but leave the code (to be executed only once), don't call handleMsg() and make WinMain like in the example below, it works like a charm. 当我不使用线程并删除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;
}

Later edit: from what I've seen, PeekMessage() always returns 0 :( 后来编辑:从我看到的,PeekMessage()总是返回0 :(

Quote from PeekMessage on Microsofts website: 在微软网站上引用PeekMessage

A handle to the window whose messages are to be retrieved. 要检索其消息的窗口句柄。 The window must belong to the current thread. 该窗口必须属于当前线程。

If hWnd is NULL, PeekMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). 如果hWnd为NULL,则PeekMessage将检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中hwnd值为NULL的任何消息(请参阅MSG结构)。 Therefore if hWnd is NULL, both window messages and thread messages are processed. 因此,如果hWnd为NULL,则处理窗口消息和线程消息。

If hWnd is -1, PeekMessage retrieves only messages on the current thread's message queue whose hwnd value is NULL, that is, thread messages as posted by PostMessage (when the hWnd parameter is NULL) or PostThreadMessage. 如果hWnd为-1,则PeekMessage仅检索当前线程的hwnd值为NULL的消息队列中的消息,即PostMessage发布的线程消息(当hWnd参数为NULL时)或PostThreadMessage。

I suspect the thread doesn't have a "current window", and the "current threads message queue" isn't the one that Windows actually posts the messages onto as the default thread. 我怀疑该线程没有“当前窗口”,并且“当前线程消息队列”不是Windows实际将消息作为默认线程发布的那个。 This is only an assumption, since it is entirely possible that there are other problems (as well?) with your approach. 这只是一个假设,因为您的方法完全可能存在其他问题(以及?)。 But I believe this is a main portion of where the problem lies. 但我相信这是问题所在的主要部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM