如何通知Windows服务中的时间更改

Bet*_*eto 4 delphi service winapi

我创建了一个WindowProc来通知系统时间变化:

constructor TJJWScheduler.Create;
begin 
  fTimeChangeWnd := Classes.AllocateHWnd(TimeChangeWndProc);
end;

procedure TJJWScheduler.TimeChangeWndProc(var msg: TMessage);
var
  i: integer;
begin
  case msg.Msg of
    WM_TIMECHANGE:
      begin
        // my things
      end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

此代码在Windows服务中运行.问题是当我改变系统时间时它不会被触发!

为什么广播消息(WM_TIMECHANGE)没有发送到我的窗口?没有循环还有另一种方法吗?


编辑

我不知道为什么,但我硬编码PeekMessage来处理消息到那个窗口,一切都工作正常.下面的代码解决了我的问题:

 var 
   msg: TMsg;

 if PeekMessage(msg, fTimeChangeWnd, WM_TIMECHANGE, WM_TIMECHANGE, PM_REMOVE) then
 begin
   TranslateMessage(msg);
   DispatchMessage(msg);
 end;
Run Code Online (Sandbox Code Playgroud)

这种解决方法非常奇怪,因为我已经有其他窗口处理消息(通过通用ProcessMessages),只有这个没有处理它的消息.

Dav*_*nan 8

您的窗口没有收到WM_TIMECHANGE消息的原因是您的窗口是从辅助线程创建的.

进程中的每个线程都有自己的消息队列.在为消息队列提供服务时会传递同步消息,因此,对于非排队消息,WM_TIMECHANGE您需要提供服务辅助线程消息队列以便传递消息.

例如,查看文档GetMessage,获取队列消息的最常用方法:

该函数调度传入的已发送消息,直到发布的消息可供检索.

同样如此PeekMessage.它在查看队列之前调度传入的已发送消息.

还有一些其他方式可以发送已发送的消息,但这些是主要的方式.

现在,我怀疑您定期从辅助线程发送消息可能不方便.如果您的辅助线程没有别的话,就可以简单地坐在传统GetMessage,TranslateMessage,DispatchMessage循环.大多数情况下,它会很快阻止GetMessage调度任何传入的已发送消息.但是如果你的辅助线程做了更多工作,那么这可能不是一个可行的选择.

您已在主服务线程上运行并为消息队列提供服务.使侦听器窗口与主服务线程具有亲缘关系可能更有意义.通过从主服务线程中运行的代码创建它来做到这一点.

另请注意,AllocateHWnd记录的不是线程安全的.您不能从进程主线程以外的任何线程调用它.因此,如果您确实希望保留在辅助线程上,则需要使用CreateWindow而不是AllocateHWnd.但这可能是将此窗口移动到主线程上的另一个好理由.

  • 我将通过调用`SetEvent`来处理主线程中的消息,以通知通常被`WaitForMultipleObjects`阻塞的辅助线程. (2认同)