2009-09-22 19 views
7

Mam główny wątek GUI, który chcę pozostać responsywny dla akcji użytkowników, takich jak przesuwanie okna dialogowego, zmiana rozmiaru itp., Podczas gdy mam wątek tła wykonujący pewne zadanie. W przeszłości używałem WaitForSingleObject z limitem czasu, aby przetwarzać zdarzenia GUI podczas czekania na zakończenie wątku tła. Ostatnio czytałem o MsgWaitForMultipleObjects, które wyglądało na rozwiązanie problemu, który miałem trochę czystszy.Zrozumienie MsgWaitForMultipleObjects

Czy ktoś może mi powiedzieć o błędach w następującym kodzie: &, gdzie się tu mylę? Gui nie odpowiada, gdy kliknę przycisk, aby rozpocząć wątek. Stworzyłem aplikację dialogową z avi odtwarzanym w głównym wątku. Mam przycisk, aby uruchomić wątek i użyć MsgWaitForMultipleObjects, aby poczekać na uchwyt wątku, ale pozwolić na przetworzenie wszystkich komunikatów, które ostatecznie zostaną przerwane, gdy wątek zostanie zakończony/zasygnalizowany.

Dzięki.

UINT MyThreadProc(LPVOID pParam) 
{ 
    ThreadData* pObject = (ThreadData*)pParam; 

    if (pObject == NULL || 
     !pObject->IsKindOf(RUNTIME_CLASS(ThreadData))) 
    return 1; 

    // Do some processing. 
    int x = 0; 
    while (x++ < 5000) 
    { 
     for (int i=0; i<50000; i++) 
      double sum = sqrt((double)i+1) * sqrt((double)i+2); 
    } 

    return 0; 
} 

Przycisk Handler

void Cmsgwait_demoDlg::OnBnClickedBtnStartThread() 
{ 
    m_pThreadData = new ThreadData; 
    CWinThread* pWorkThread = AfxBeginThread(MyThreadProc, m_pThreadData); 

    m_status.SetWindowText("Status: Waiting for thread to complete."); 

    HANDLE handles[] = { pWorkThread->m_hThread }; 
    DWORD ret = 0; 

    do 
    { 
     ret = MsgWaitForMultipleObjects(1, handles, FALSE, INFINITE, QS_ALLINPUT); 
     if (ret == WAIT_OBJECT_0) 
     { 
      m_status.SetWindowText("Status: Thread completed."); 
     } 
     else if (WAIT_IO_COMPLETION) 
     { 
      m_status.SetWindowText("Status: User mode APC queued."); 
     } 
     else if (WAIT_FAILED) 
     { 
      m_status.SetWindowText("Status: Wait failed"); 
     } 
    } 
    while (ret != WAIT_OBJECT_0 && ret != WAIT_FAILED); 
} 

Odpowiedz

13

Nie jesteś przetwarzanie przychodzących wiadomości z wątku UI, brać look at Raymond's blog (patrz również here) dla próbki.

while (true) { 
    switch (MsgWaitForMultipleObjects(1, &h, 
         FALSE, INFINITE, QS_ALLINPUT)) { 
    case WAIT_OBJECT_0: 
     DoSomethingWith(h); // event has been signalled 
     break; 
    case WAIT_OBJECT_0+1: 
     // we have a message - peek and dispatch it 
     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 
     // TODO: must handle WM_QUIT; see Raymond's blog for details 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
     } 
     break; 
    default: 
     return FALSE; // unexpected failure 
    } 
    } 
+0

Tak, to będzie to. Dzięki. –

+3

NIEBEZPIECZEŃSTWO Ten kod zawiera błąd, o którym pisał Raymond. Musisz zapętlić się na ekran podglądu. –

+2

5 upvotes i próbka ma kilka niebezpiecznych błędów ... naprawionych (bez obrazy dla oryginalnego autora). –