只是检查在编写 Windows 服务时是否有任何最佳实践。
Service(单线程)需要定时工作,目前只能想到:
- 使用 sleep(),然后循环检查时间?
- 使用 TTimer?
有什么建议吗?
最佳答案
您的服务是单线程的并不重要,因为服务将始终在不同的线程上下文中调用其代码:
服务管理器将启动、停止、暂停和恢复服务执行,并请求当前服务状态。
服务本身将至少有一个线程执行真正的工作,它需要对来自服务管理器的请求使用react,根据请求更改服务执行状态,并返回请求的信息。服务需要在相当短的时间内响应来自服务管理器的请求,否则它会认为服务已挂起并杀死它。这就是为什么 - 如果服务可能有长时间执行或阻塞的代码 - 拥有多个服务线程可能会更好。
是否使用 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;
这在循环中使用了 Sleep(),但是解决方案使用了
while integer(GetMessage(Msg, HWND(0), 0, 0)) > 0 do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
也可以,然后可以使用 Windows 计时器消息。
关于Windows 服务 : Do work at specified times (Delphi),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1073351/