2010-10-01 1 views
0

У меня есть основная программа, которая создает потоки в порядке: ThreadB then ThreadA (которому передан ID ThreadB) с использованием функции CreateThread.Темы winapi требуют времени для инициализации перед передачей сообщений?

Нить A отправляет сообщение в Thread B, используя PostThreadMessage. B получает сообщение с помощью GetMessage.

Проблема, с которой я столкнулась, заключается в том, что PostThreadMessage блокируется случайным образом при первом вызове и никогда не возвращается, иногда программа отлично работает, в других случаях я запускаю программу и блокирует использование 0 CPU при первом postthreadmessage. Однако, если я добавлю Sleep (10) в ThreadA до первого PostThreadMessage, я никогда, похоже, не воспользуюсь этой проблемой.

Что мне не хватает о сроках потоков и сообщений?

ответ

4

Вы не можете отправить сообщение в поток, пока не появится очередь сообщений. Очереди сообщений не создаются, пока этот поток не вызовет такую ​​функцию, как GetMessage или PeekMessage. То, что ваш сон делает, задерживает поток отправки достаточно долго, чтобы принимающий поток вызывал GetMessage и настраивал очередь сообщений.

Кстати, я настоятельно рекомендую не использовать PostThreadMessage, так как сообщения могут потеряться. Лучше создать окно сообщений (с родителем HWND_MESSAGE) в принимающем потоке и вместо этого отправлять сообщения.

1

Чтобы добавить к правильному ответу Энтони Уильямса, код, который я использую для решения этой проблемы, выглядит следующим образом. У меня есть класс, похожий на MyThread ...

void MyThread::Start() 
{ 
    m_hResumeMain = CreateEvent(NULL,FALSE,FALSE,NULL); 
    m_hThread = CreateThread(NULL,0,ThreadProc,this,0,&m_dwThreadId); 
    WaitForSingleObject(m_hResumeMain,INFINITE); 
    CloseHandle(m_hResumeMain); 
    m_hResumeMain=0; 
} 

DWORD MyThread::ThreadProc(LPVOID pv) 
{ 
    MyThread* self = (MyThread*)pv; 
    return self->ThreadProc(); 
} 

DWORD MyThread::ThreadProc() 
{ 
    MSG msg; 
    // Create the thread message queue 
    PeekMessage(&msg,0,0,0,PM_NOREMOVE); 
    // Resume the main thread 
    SetEvent(m_hResumeMain); 
    while(GetMessage(&msg,0,0,0)>0){ 
    if(msg.hwnd){ 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    else { 
    DoThreadMessage(&msg); 
    } 
    } 
    return 0; 
} 

Суть вопроса является вы в конечном счете, не может полагаться на Sleep, чтобы гарантировать, что рабочий поток достаточно инициализирован. Плюс, в общем, обычно существует некоторая небольшая сумма работы, которую должен выполнять рабочий поток до возобновления потока запуска. Поэтому создайте объект события перед созданием потока, дождитесь его в основном потоке и сообщите об этом в рабочий поток после завершения инициализации.