Потоки winapi требуют времени для инициализации, прежде чем сработает передача сообщений? - PullRequest
0 голосов
/ 01 октября 2010

У меня есть основная программа, которая создает потоки в следующем порядке: ThreadB тогда ThreadA (которому передается идентификатор ThreadB) используя функцию CreateThread.

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

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

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

Ответы [ 2 ]

4 голосов
/ 01 октября 2010

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

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

1 голос
/ 01 октября 2010

Чтобы добавить к Энтони Уильямсу правильный ответ, код, который я использую для решения этой проблемы, выглядит следующим образом.У меня есть класс, похожий на 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, чтобы гарантировать, что рабочий поток достаточно инициализирован.Кроме того, как правило, существует небольшой объем работы, которую должен выполнить рабочий поток, прежде чем запускать поток запуска можно будет возобновить.Поэтому создайте объект события перед созданием потока, дождитесь его в основном потоке и подайте сигнал рабочему потоку после завершения инициализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...