Отказ от ответственности: Я немного полезен, когда речь заходит о многопоточности. Я читал материал в Интернете, сделал несколько простых многопоточных примеров.GDI + чертеж с многопотоковой обработкой
У меня есть приложение 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 функции, которые привлекают & обработки сообщений весьма simplist. Цикл 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(), но оставить код (будет выполняться только один раз), не называйте 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 являются потокобезопасными. Я настроен скептически, но это очень сложно доказать. Никто не знает, как сохранить свою собственную программу в потоковом режиме для каждого * окна и * каждого * сообщения. Понятно, что у вас нет, вы не пытаетесь блокировать отправку сообщений с помощью чертежа.Вам намного лучше не пытаться, в лучшем случае вы можете сделать рендеринг в работе back-buffer и перелистывать страницы. При правильной блокировке вы, вероятно, можете заставить это работать. –