GetMessage中的wparam值不是我所期望的(DelphiXE4)



我有一个正在开发的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。我错过了什么?

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

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消息(不是专门用于服务),并使用其他机制进行通信

最新更新