Значение wparam в GetMessage не соответствует ожиданиям (Delphi XE4)

У меня есть приложение-служба Delphi XE4 в разработке. Служба запускает потоки для некоторых длительных задач, и потоки сообщают о состоянии обратно с помощью вызова PostThreadMessage.

Основной цикл ServiceExecute выглядит следующим образом:

procedure TScanService.ServiceExecute(Sender: TService);
var
  CurrentMessage: TMsg;
begin
  LogServerEvent('ServiceExecute', 'Starting');
  while not Terminated do
  begin
    if not PeekMessage(CurrentMessage, 0, WM_NULL, msgHigh, PM_NOREMOVE) then
    begin
      Sleep(1000);
      Continue;
    end;

    GetMessage(CurrentMessage, 0, WM_NULL, msgHigh);

    LogServerEvent('ServiceExecute', 'CurrentMessage.message', IntToStr(CurrentMessage.message));
    LogServerEvent('ServiceExecute', 'CurrentMessage.wParam', IntToStr(CurrentMessage.wParam));
    LogServerEvent('ServiceExecute', 'CurrentMessage.lParam', IntToStr(CurrentMessage.lParam));

В ветке отправка сообщения выглядит так:

    gThreadNumber: Integer;

    LogThreadEvent('Execute', 'Found Notice, Thread number: ' + IntToStr(gThreadNumber));
    PostThreadMessage(ParentThreadID, msgFound, gThreadNumber, 6);

Сообщение приходит нормально, и номер сообщения правильный (msgFound = WM_USER + 1); однако я послал 0, 6 для wParam, lParam, и я получил 4, 0. Чего мне не хватает?

Примечание. В коде работают только 2 потока, и один из них представляет собой таймер, который использует другой номер сообщения и ничего не отправляет, когда это происходит.

1 ответ

В TService код вы можете найти этот код:

const
  CM_SERVICE_CONTROL_CODE = WM_USER + 1;
....
procedure TService.Controller(CtrlCode: DWord);
begin
  PostThreadMessage(ServiceThread.ThreadID, CM_SERVICE_CONTROL_CODE, CtrlCode, 0);
  if ServiceThread.Suspended then ServiceThread.Resume;
end;

Так TService отправляет сообщения с тем же номером сообщения, что и ваши сообщения. Как вы можете отличить их? Ну, ты не можешь.

Из документации для WM_USER:

Используется для определения личных сообщений для использования классами частного окна, обычно в форме WM_USER+x, где x - целочисленное значение.

Обычно это используется для сообщений, отправляемых окну, и значение сообщения зависит от класса. Пока я читаю TService В коде разработчики взяли точку зрения, что они полностью контролируют очередь сообщений и имеют право определять смысл своих личных сообщений. Конечным результатом этого является то, что вы не можете использовать сообщения потока в WM_USER диапазон, потому что они были зарезервированы TService учебный класс.

Ваши основные варианты:

  • Отправляйте свои сообщения в окно.
  • использование RegisterWindowMessage обеспечить уникальность идентификатора сообщения.
  • Прекратите использовать сообщения Windows (не специально предназначенные для использования в службе) и общайтесь, используя какой-либо другой механизм.
Другие вопросы по тегам