Понимание MsgWaitForMultipleObjects - PullRequest
8 голосов
/ 22 сентября 2009

У меня есть основной поток графического интерфейса, который я хочу реагировать на действия пользователей, такие как перемещение диалога, изменение размера и т. Д., Пока у меня есть фоновый поток, выполняющий некоторую задачу. В прошлом я использовал WaitForSingleObject с таймаутом для обработки событий графического интерфейса во время ожидания завершения фонового потока. Недавно я читал о MsgWaitForMultipleObjects, который, похоже, решал проблему, которая у меня была немного чище.

Может кто-нибудь сказать мне ошибки в следующем коде и где я здесь не так? Графический интерфейс не отвечает, когда я нажимаю кнопку, чтобы начать поток. Я сделал диалоговое приложение с AVI, который играет в основном потоке пользовательского интерфейса. У меня есть кнопка, чтобы запустить поток и использовать MsgWaitForMultipleObjects для ожидания на дескрипторе потока, но позволяет обрабатывать все сообщения, в конечном счете, прерываясь, когда поток завершается / сигнализируется.

Спасибо.

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;
}

Обработчик кнопок

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);
}

1 Ответ

14 голосов
/ 22 сентября 2009

Вы не обрабатываете входящее сообщение из потока пользовательского интерфейса, посмотрите на , посмотрите в блоге Рэймонда (см. Также здесь ) для примера.

  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
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...