简体   繁体   中英

wparam value in GetMessage not what I expected (Delphi XE4)

I have a Delphi XE4 service application under development. The service starts threads for some long-running tasks, and the threads communicate status back with a PostThreadMessage call.

The main ServiceExecute loop looks like this:

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));

In the thread, the message sending looks like this:

    gThreadNumber: Integer;

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

The message arrives fine, and the message number is correct (msgFound = WM_USER + 1); however, I sent 0, 6 for wParam, lParam, and what I received is 4, 0. What am I missing?

Note: The code only has 2 threads running, and one is a timer that uses a different message number, and isn't sending anything when this happens.

In the TService code you can find this code:

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;

So TService is sending messages with the same message number as your messages. How can you tell them apart? Well, you cannot.

From the documentation for WM_USER :

Used to define private messages for use by private window classes, usually of the form WM_USER+x, where x is an integer value.

Usually this would be used for messages sent to a window and the meaning of the message would be class specific. As I read the TService code, the designers have taken the point of view that they are in full control of the message queue and have the right to determine the meaning of its private messages. The net result of this, is that you cannot use thread messages in the WM_USER range because they have been reserved by the TService class.

Your main options:

  • Send your messages to a window.
  • Use RegisterWindowMessage to ensure message id uniqueness.
  • Stop using windows messages (not especially intended for use in a service) and communicate using some other mechanism.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM