проблема postthreadmessage и peekmessage в delphi 2006

Я создал многодетное приложение. Все окна приложений (W[n]: TMyWindows) одинаковы, и все они имеют связанный с ними частный экземпляр класса объектов (E: TMyObject). Дочерние окна генерируют через эти объекты некоторые сообщения. Я создал в основном приложении два потока, которые обрабатывают эти сообщения в зависимости от их содержимого. Например, давайте сделаем следующие асинхронные вызовы:

W[1].E.Service(thread1service)
W[2].E.Service(thread2service)

TMyObject.Service(тип службы)

case servicetype of
  thread1service: PostThreadMessage(thread1id,...);
  thread2service: PostThreadMessage(thread2id,...);
end;

Теперь в методе выполнения каждого потока у меня есть что-то вроде этого:

while not terminated do
begin
 ...
 if peekmessage(msg,0,thread1message_1,thread1message_n,pm_remove) then
      process message
 do other things;
end

Все идет нормально, за исключением того, что второй поток не получает никаких сообщений. У вас есть идеи, почему?


person zoomz    schedule 17.09.2009    source источник


Ответы (3)


Я бы проверил, чтобы убедиться, что диапазон, который вы предоставляете PeekMessage(), действителен. Попробуйте вместо этого ввести нули, чтобы получать все сообщения, например:

PeekMessage(msg, 0, 0, 0, PM_REMOVE)

Если это не сработает, я бы проверил результат функции PostThreadMessage()... Возможно, поток еще не вызвал PeekMessage(), поэтому Windows создает для вас очередь сообщений.

Как указано в этой статье (в разделе " Remarks"), вы можете либо проверить результат вызова PostThreadMessage() и Sleep() в случае неудачи, либо использовать событие, чтобы сообщить основному потоку, что дочерний поток готов получать сообщения.

ХТХ,

N@

person Nat    schedule 18.09.2009

Поэтому мне пришлось сдаться, так как я не нашел никакого рационального объяснения.

Я решил отправлять сообщения, используя критическую секцию с сигнализацией событий, чтобы сообщить рабочим потокам, что у них есть сообщение для обработки. К сожалению, это означает, что основной поток должен проверять, обрабатывает ли рабочий поток какое-либо сообщение перед отправкой нового.

person zoomz    schedule 20.09.2009
comment
Не обязательно. Дайте каждому потоку очередь FIFO, защищенную критическим разделом, и добавьте событие для ожидания. Сигнализировать о событии, когда FIFO не пуст. - person mghie; 20.09.2009
comment
Я думал об этом, но тогда, если основной поток поставит в очередь много сообщений, рабочий поток будет вынужден их обрабатывать, а рабочий поток выполняет некоторые критические задачи в своем цикле. Поэтому, если рабочий поток обрабатывает какое-либо сообщение, основной поток просто сбрасывает новые сообщения, а не отправляет их рабочему потоку. - person zoomz; 20.09.2009
comment
Печально, но очередь сообщений потока была бы идеальной. Мне все еще интересно, почему это не работает для вас. Я проверил свою реализацию этого, и вы, похоже, не делаете ничего плохого из того, что говорите. :( - person Nat; 22.09.2009

Я знаю, что это старый вопрос, но у меня только что была похожая проблема в нашем коде. Мы запускаем Delphi 2006 на 64-разрядной версии Win 7, и рассматриваемый код включает связь DLL с отдельным приложением через peekmessage/postthreadmessage.

В конце концов мне удалось проследить проблему до прав администратора, предоставленных либо приложению, либо Delphi. Режим совместимости также вызывает проблему, так как требует предоставления прав администратора. Если предоставлены права администратора, поток администратора может общаться с потоком без прав администратора, но поток без прав администратора не может отправить сообщение обратно в поток с правами администратора. Вызов PostThreadMessage в приложении без прав администратора сообщал об успехе, но сообщение никогда не появлялось в очереди сообщений целевого приложения.

Я не решил проблему, но, к счастью, смог запустить приложение в обычном режиме, так что это не было проблемой, кроме потерянного времени в погоне за ним.

person Matt Allwood    schedule 04.04.2012