忙时重启服务

发布于 2025-01-18 10:49:10 字数 1208 浏览 0 评论 0原文

我使用 Delphi XE2 编写了 Windows 服务应用程序。 最近我注意到Windows更新后服务无法启动。日志告诉我服务正忙于睡眠。

我有

procedure TnSoftTestService.TestCheckEverything;
var
  i: Integer;
begin
  for i := 0 to 24 do
  begin
    Sleep(1000);
    LogToFile(IntToStr(ord(nSoftTestService.Status)), TLogMsgType.ltDebug);
  end;
end;

procedure TnSoftTestService.ServiceCreate(Sender: TObject);
begin
  LogToFile('Servisas kuriamas', TLogMsgType.ltDebug);
end;

procedure TnSoftTestService.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  LogToFile('statring', TLogMsgType.ltWarning);
  Application.CreateForm(TdmMainDataModule, dmMainDataModule);
  dmMainDataModule.svsRysiams.active := True;
end;

procedure TnSoftTestService.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  LogToFile('Servisas stabdomas', TLogMsgType.ltWarning);
end;

dmMainDataModule 包含我连接到并执行 TnSoftTestService.TestCheckEverything; 的 TServerSocket。当它处于循环状态时,我重新启动服务。我在 Windows 服务中收到“服务正在停止”,然后收到“服务正在启动”,但我没有收到 ServiceStart 日志,在睡眠循环后,我收到 ServiceStop 日志,并且服务已完全启动停了下来。如果我不执行TestCheckEverything,我确实会得到它们。我应该把长时间睡眠放在哪里以及如何检测服务正在重新启动?

I have written windows service application using Delphi XE2.
Recently I noticed that service failed to start after Windows update. Logs told me that service was busy doing sleep.

I have

procedure TnSoftTestService.TestCheckEverything;
var
  i: Integer;
begin
  for i := 0 to 24 do
  begin
    Sleep(1000);
    LogToFile(IntToStr(ord(nSoftTestService.Status)), TLogMsgType.ltDebug);
  end;
end;

procedure TnSoftTestService.ServiceCreate(Sender: TObject);
begin
  LogToFile('Servisas kuriamas', TLogMsgType.ltDebug);
end;

procedure TnSoftTestService.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  LogToFile('statring', TLogMsgType.ltWarning);
  Application.CreateForm(TdmMainDataModule, dmMainDataModule);
  dmMainDataModule.svsRysiams.active := True;
end;

procedure TnSoftTestService.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  LogToFile('Servisas stabdomas', TLogMsgType.ltWarning);
end;

dmMainDataModule contains TServerSocket that i connect to and execute TnSoftTestService.TestCheckEverything;. while it is in a loop, i restart service. I get "Service is stopping" and then "Service is starting" in Windows services, but i get no ServiceStart logs and after sleep loop i get ServiceStop log and service is completely stopped. I do get them if I do not execute TestCheckEverything. Where should I put my long sleep and how do i detect that service is being restarted?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡莣 2025-01-25 10:49:10

问题在于testcheckeverything正在阻止tserversocket,因此服务,从及时关闭。当服务需要关闭时,它需要停止循环。例如,您应该在服务的onstop/onshutdown事件中设置标志,并定期使循环查看该标志。

另外,您不应从onstop/onshutdown事件退出,直到服务完全清除了所需的内容,即<<代码> tserversocket 已完全停用。

尝试更多类似的东西:

private
  ShuttingDown: Boolean;

procedure TnSoftTestService.TestCheckEverything;
var
  i: Integer;
begin
  for i := 0 to 24 do
  begin
    if ShuttingDown then Exit;
    Sleep(1000);
    LogToFile(IntToStr(ord(nSoftTestService.Status)), TLogMsgType.ltDebug);
  end;
end;

procedure TnSoftTestService.ServiceCreate(Sender: TObject);
begin
  LogToFile('Servisas kuriamas', TLogMsgType.ltDebug);
end;

procedure TnSoftTestService.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  LogToFile('starting', TLogMsgType.ltWarning);
  dmMainDataModule := TdmMainDataModule.Create(nil);
  dmMainDataModule.svsRysiams.Active := True;
  Started := True;
end;

procedure TnSoftTestService.ServiceStop(Sender: TService;
  var Stopped: Boolean);
begin
  ServiceShutdown(Sender);
  Stopped := True;
end;

procedure TnSoftTestService.ServiceShutdown(Sender: TService);
begin
  LogToFile('Servisas stabdomas', TLogMsgType.ltWarning);
  ShuttingDown := True;
  dmMainDataModule.svsRysiams.Active := False;
  dmMainDataModule.Free;
  CoUninitializeEx;
end;

另外,请考虑使用tevent而不是sleep(),例如:

private
  ShuttingDown: TEvent;

procedure TnSoftTestService.TestCheckEverything;
var
  i: Integer;
begin
  for i := 0 to 24 do
  begin
    if ShuttingDown.WaitFor(1000) <> wrTimeout then Exit;
    LogToFile(IntToStr(ord(nSoftTestService.Status)), TLogMsgType.ltDebug);
  end;
end;

procedure TnSoftTestService.ServiceCreate(Sender: TObject);
begin
  LogToFile('Servisas kuriamas', TLogMsgType.ltDebug);
  ShuttingDown := TEvent.Create;
end;

procedure TnSoftTestService.ServiceDestroy(Sender: TObject);
begin
  ShuttingDown.Free;
end;

procedure TnSoftTestService.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  LogToFile('starting', TLogMsgType.ltWarning);
  ShuttingDown.ResetEvent;
  dmMainDataModule := TdmMainDataModule.Create(nil);
  dmMainDataModule.svsRysiams.Active := True;
  Started := True;
end;

procedure TnSoftTestService.ServiceStop(Sender: TService;
  var Stopped: Boolean);
begin
  ServiceShutdown(Sender);
  Stopped := True;
end;

procedure TnSoftTestService.ServiceShutdown(Sender: TService);
begin
  LogToFile('Servisas stabdomas', TLogMsgType.ltWarning);
  ShuttingDown.SetEvent;
  dmMainDataModule.svsRysiams.Active := False;
  dmMainDataModule.Free;
  CoUninitializeEx;
end;

The problem is that TestCheckEverything is blocking the TServerSocket, and thus the service, from shutting down in a timely manner. It needs to stop looping when the service needs to shut down. For example, you should set a flag in the service's OnStop/OnShutdown events, and have the loop look at that flag periodically.

Also, you should not be exiting from the OnStop/OnShutdown events until the service has completely cleaned up what it needs to, ie after the TServerSocket has been fully deactivated.

Try something more like this:

private
  ShuttingDown: Boolean;

procedure TnSoftTestService.TestCheckEverything;
var
  i: Integer;
begin
  for i := 0 to 24 do
  begin
    if ShuttingDown then Exit;
    Sleep(1000);
    LogToFile(IntToStr(ord(nSoftTestService.Status)), TLogMsgType.ltDebug);
  end;
end;

procedure TnSoftTestService.ServiceCreate(Sender: TObject);
begin
  LogToFile('Servisas kuriamas', TLogMsgType.ltDebug);
end;

procedure TnSoftTestService.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  LogToFile('starting', TLogMsgType.ltWarning);
  dmMainDataModule := TdmMainDataModule.Create(nil);
  dmMainDataModule.svsRysiams.Active := True;
  Started := True;
end;

procedure TnSoftTestService.ServiceStop(Sender: TService;
  var Stopped: Boolean);
begin
  ServiceShutdown(Sender);
  Stopped := True;
end;

procedure TnSoftTestService.ServiceShutdown(Sender: TService);
begin
  LogToFile('Servisas stabdomas', TLogMsgType.ltWarning);
  ShuttingDown := True;
  dmMainDataModule.svsRysiams.Active := False;
  dmMainDataModule.Free;
  CoUninitializeEx;
end;

Alternatively, consider using a TEvent instead of Sleep(), eg:

private
  ShuttingDown: TEvent;

procedure TnSoftTestService.TestCheckEverything;
var
  i: Integer;
begin
  for i := 0 to 24 do
  begin
    if ShuttingDown.WaitFor(1000) <> wrTimeout then Exit;
    LogToFile(IntToStr(ord(nSoftTestService.Status)), TLogMsgType.ltDebug);
  end;
end;

procedure TnSoftTestService.ServiceCreate(Sender: TObject);
begin
  LogToFile('Servisas kuriamas', TLogMsgType.ltDebug);
  ShuttingDown := TEvent.Create;
end;

procedure TnSoftTestService.ServiceDestroy(Sender: TObject);
begin
  ShuttingDown.Free;
end;

procedure TnSoftTestService.ServiceStart(Sender: TService;
  var Started: Boolean);
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  LogToFile('starting', TLogMsgType.ltWarning);
  ShuttingDown.ResetEvent;
  dmMainDataModule := TdmMainDataModule.Create(nil);
  dmMainDataModule.svsRysiams.Active := True;
  Started := True;
end;

procedure TnSoftTestService.ServiceStop(Sender: TService;
  var Stopped: Boolean);
begin
  ServiceShutdown(Sender);
  Stopped := True;
end;

procedure TnSoftTestService.ServiceShutdown(Sender: TService);
begin
  LogToFile('Servisas stabdomas', TLogMsgType.ltWarning);
  ShuttingDown.SetEvent;
  dmMainDataModule.svsRysiams.Active := False;
  dmMainDataModule.Free;
  CoUninitializeEx;
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文