2010-10-01 2 views
0

J'ai un programme principal qui crée les threads dans l'ordre: ThreadB puis ThreadA (qui est passé l'ID de ThreadB) en utilisant la fonction CreateThread. Le thread A envoie un message à Thread B en utilisant PostThreadMessage.Les threads winapi prennent le temps de s'initialiser avant le passage du message?

B reçoit le message à l'aide de GetMessage. Le problème que j'ai est que PostThreadMessage bloque aléatoirement la première fois qu'il est appelé et ne retourne jamais, quelques fois le programme funs bien, d'autres fois j'exécute le programme et il bloque avec 0 utilisation du CPU au premier message postthread. Cependant, si j'ajoute Sleep (10) à ThreadA avant le premier PostThreadMessage, je ne semble jamais rencontrer ce problème.

Que manque-t-il à propos du timing des threads et des messages?

Répondre

4

Vous ne pouvez pas envoyer un message à un thread tant qu'il n'a pas de file d'attente de messages. Les files d'attente de messages ne sont pas créées tant que ce thread n'appelle pas une fonction telle que GetMessage ou PeekMessage. Ce que fait votre sommeil est de retarder le thread d'envoi assez longtemps que le thread de réception a appelé GetMessage et configurer sa file d'attente de messages.

Incidemment, je recommande fortement de ne pas utiliser PostThreadMessage car les messages peuvent être perdus. Il est préférable de créer une fenêtre réservée aux messages (avec un parent de HWND_MESSAGE) sur le thread de réception et d'envoyer des messages à celle-ci à la place.

1

Pour ajouter à Anthony Williams réponse correcte, le code que j'utilise pour faire face à cela ressemble. J'ai une classe similaire à 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; 
} 

Le nœud du problème est que vous pouvez finalement pas compter sur un Sleep pour garantir que le thread de travail est suffisamment initialisé. De plus, en général, il y a généralement une quantité minimale de travail qu'un thread de travail doit avoir fait avant de pouvoir reprendre le thread de lancement. Créez donc un objet événement avant de créer le thread, attendez-le sur le thread principal et signalez-le sur le thread de travail une fois l'initialisation terminée.

Questions connexes