2013-07-16 2 views
0

Отказ от ответственности: Я немного полезен, когда речь заходит о многопоточности. Я читал материал в Интернете, сделал несколько простых многопоточных примеров.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 :(

+0

Существует слухи о том, что Windows user32 и gdi являются потокобезопасными. Я настроен скептически, но это очень сложно доказать. Никто не знает, как сохранить свою собственную программу в потоковом режиме для каждого * окна и * каждого * сообщения. Понятно, что у вас нет, вы не пытаетесь блокировать отправку сообщений с помощью чертежа.Вам намного лучше не пытаться, в лучшем случае вы можете сделать рендеринг в работе back-buffer и перелистывать страницы. При правильной блокировке вы, вероятно, можете заставить это работать. –

ответ

2

Цитата из PeekMessage на сайте Microsofts:

Дескриптор окна чьи сообщения должны быть получены. Окно должно принадлежать к текущей резьбе.

Если hWn d является NULL, PeekMessage извлекает сообщения для любого окна, которое относится к текущему потоку, и любые сообщения в текущей очереди сообщений потока , чье значение hwnd равно NULL (см. структуру MSG ). Поэтому, если hWnd NULL, обрабатываются как оконные сообщения, так и поток .

Если HWND равен -1, PeekMessage извлекает только сообщения об очереди сообщений текущего потока которого HWND значение NULL, то есть нить сообщения, которые разместил PostMessage (когда параметр HWND является NULL) или PostThreadMessage.

Я подозреваю, что нить не имеет «текущего окна», а «текущая очередь сообщений о потоках» - это не то, что Windows фактически размещает сообщения в качестве потока по умолчанию. Это только предположение, так как вполне возможно, что с вашим подходом есть и другие проблемы (а?). Но я считаю, что это основная часть проблемы.

+0

Спасибо за хедз-ап на окне. Вы правы, это проскользнуло мною. Тем не менее, приложение все еще зависает :(PeekMessage() продолжает возвращаться 0. –

+0

И есть ли что-то, отправляющее сообщения в очередь, на которую вы смотрите? –

+0

Нужные сообщения следует отправлять/получать, когда окно активируется или нет, или когда он уничтожается и т. д. Они обрабатываются моим WndProc(). После того, как приложение запускается, окно становится невосприимчивым. Код довольно просто написан, без потокобезопасности (просто экспериментирование с многопоточным), поэтому может быть тонна ошибок –

Смежные вопросы