2

我正在开发一个 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);但是,我为 wParam、lParam 发送了 0、6,而我收到的是 4、0。我错过了什么?

注意:代码只有 2 个线程在运行,其中一个是使用不同消息编号的计时器,发生这种情况时不发送任何内容。

4

1 回答 1

0

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确保消息 ID 的唯一性。
  • 停止使用 Windows 消息(不是专门用于服务)并使用其他机制进行通信。
于 2015-02-27T20:56:08.010 回答