Windows服务:在指定时间工作(Delphi)

Atl*_*las 6 windows delphi winapi

只需检查编写Windows服务时是否有任何最佳实践.

服务(单线程)需要按指定的时间间隔工作,现在我只能想到:

  1. 使用sleep(),然后检查循环中的时间?
  2. 使用TTimer?

有什么建议?

mgh*_*hie 14

您的服务是单线程并不重要,因为服务将始终在不同的线程上下文中调用其代码:

  • 服务管理器将启动,停止,暂停和恢复服务执行,并请求当前服务状态.

  • 服务本身将至少有一个执行实际工作的线程,需要对来自服务管理器的请求作出反应,根据请求更改服务执行状态,并返回所请求的信息.服务需要在合理的短时间内响应来自服务管理器的请求,否则它会认为服务被挂起并将其终止.这就是原因 - 如果服务可能有长期执行或阻塞代码 - 拥有多个服务线程可能会更好.

是否使用Sleep()或定时器消息还取决于服务线程中消息泵的可用性.如果您没有消息泵,则应使用Sleep()或计时器回调.如果你有一个消息泵,因为你需要通过Windows消息与其他进程或线程通信,或者你需要做OLE的东西,那么使用定时器消息可能是最容易的.

几年前,我编写了一个服务,用于定时执行任务,类似于Windows at或Unix cron功能.它不使用大部分VCL,只使用一些基类.该服务的Run()方法如下所示:

procedure TScheduleService.Run;
var
  RunState: TServiceRunState;
begin
  while TRUE do begin
    RunState := GetServiceRunState;
    if (RunState = srsStopped) or (fEvent = nil) then
      break;
    if RunState = srsRunning then begin
      PeriodicWork;
      Sleep(500);
    end else
      fEvent.WaitFor(3000);
    Lock;
    if fServiceRunStateWanted <> srsNone then begin
      fServiceRunState := fServiceRunStateWanted;
      fServiceRunStateWanted := srsNone;
    end;
    Unlock;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

这在循环中使用Sleep(),但使用的是解决方案

while integer(GetMessage(Msg, HWND(0), 0, 0)) > 0 do begin
  TranslateMessage(Msg);
  DispatchMessage(Msg);
end;
Run Code Online (Sandbox Code Playgroud)

也会工作,然后可以使用Windows计时器消息.


Jam*_*mie 10

这需要是一项服务吗?你可以在Windows中设置一个预定的任务吗?