【发布时间】:2013-07-16 12:51:07
【问题描述】:
免责声明:我在多线程方面有点菜鸟。我在网上读过一些东西,做过一些简单的多线程示例。
我有一个 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 :(
【问题讨论】:
-
有传言说 Windows user32 和 gdi 是线程安全的。我持怀疑态度,但它非常很难证明。没有人知道如何为每个窗口和每个消息保持他们自己的程序线程安全。显然你的不是,你没有尝试将消息发送与绘图联锁。你最好不要尝试,充其量你可以在后台缓冲区中进行渲染并翻页。通过适当的锁定,您可能可以让它发挥作用。
标签: c++ multithreading winapi gdi+