【问题标题】:what is the maximum time windows service wait to process stop request and how to request for additional timeWindows 服务等待处理停止请求的最长时间以及如何请求额外时间
【发布时间】:2012-11-07 09:21:23
【问题描述】:

我用 c# 编写了一个处理大量数据的 Windows 服务。当我们停止它尝试某个时间 20/30 秒然后抛出异常。

我想在 OnStop 事件中实现 ServiceBase.RequestAdditionalTime()。

我想知道 Windows 服务抛出异常的确切超时时间,以便我可以在它之前请求额外的时间。

我搜索但没有找到这个默认的停止超时值。

【问题讨论】:

标签: c# .net windows-services


【解决方案1】:

我写了下面的代码来实现它。

protected override void OnStop()
{
  int timeout = 10000;
  var task = Task.Factory.StartNew(() => MyTask());
  while (!task.Wait(timeout))
  {
      RequestAdditionalTime(timeout);
  }
}

上面的代码启动了一个与主线程并行的任务(任务立即开始运行),下一行是每 10 秒检查一次任务是否完成,如果没有完成,则请求额外的 10 秒并继续检查直到任务完成。

【讨论】:

  • @Imran Rizvi,RequestAdditionalTime 中是否有总时间限制?前10秒,后10秒,后10秒,后10秒……能坚持1小时吗?
  • Chris Kline 的回答提供了很多关于内部运作的有用细节,这些细节自 4 年前和 OP 7 年后发布以来仍然相关。
  • 此代码包含一个微妙的问题:如果您请求与循环对峙延迟相同的额外延迟,并且 Task.Wait 滑动,您的线程可能仍然比硬系统超时更早被杀死。
【解决方案2】:

操作系统重启的不同设置

尽管很多人提到了HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout 注册表项,但根据this "Service Control Handler" article from Microsoft 的说法,该注册表项控制服务可以关闭的最长时间何时Windows 本身正在关闭或重新启动

<...> 防止服务停止关闭,有一个限制 服务控制器等待多长时间。如果服务被关闭 通过服务管理单元向下,限制为 125 秒。如果 操作系统正在重新启动,时间限制在 WaitToKillServiceTimeout 值 <...>

如果 Windows 未处于重新启动或关闭过程中,则 Windows 等待服务关闭的默认时间为 30 秒。但是,应用程序可以请求额外的时间,这将得到最多 125 秒的总时间(所有请求的总和)。

在 Windows Server 2003 及更高版本上,可以通过HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ServicesPipeTimeout 注册表项更改此默认超时,如this Microsoft support article(和this ServerFault question)中所述。不清楚这是否适用于 Windows 7/8/10,因为文章只提到了服务器版本。

如果已在计算机上启动重新启动/关闭WaitToKillServiceTimeout 注册表项值(如果存在)指定 Windows 允许应用程序被允许的最长时间,覆盖操作系统默认。

大概是这样,应用程序不能任意延迟关闭超出默认值(或管理员通过WaitToKillServiceTimeout 注册表项指定的值)。

【讨论】:

  • 看来我系统上的默认超时时间是 125 秒,用于通过“服务”mmc 停止服务。更改 ServicesPipeTimeout 似乎没有任何影响。设置为 30,000 毫秒,它仍然让服务有 125 秒的时间停止。
【解决方案3】:

它在子键的注册表中设置:

 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

字符串值为WaitToKillServiceTimeout。如果未定义,则默认为 20000 (ms)。在我的机器上,它似乎设置为 12000 (12s)。我从来没有碰过它。

【讨论】:

    【解决方案4】:

    默认情况下我相信它是 12000 毫秒,要更改它你需要访问注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout 并更改值

    但是如果你想启动它或停止它编程,你可以定义你自己的超时时间 在这里你定义你自己的开始时间

    TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
    service.Start();
    service.WaitForStatus(ServiceControllerStatus.Running, timeout);
    

    在这里你定义你自己的停止时间

     TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
     service.Stop();
     service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
    

    【讨论】:

    • 这在使用内置 Windows 工具(如 sc.exe 或“服务”mmc 插件)时无济于事。
    • 是的,但我包括的是在语法上做停止和重新启动
    • 那么你应该指出这个事实。因为严格来说,这不是 OP 问题的答案。
    • 在哪里编写代码?我有 OnStop 重写方法来处理数据,我没有在其中写 .Stop 任何地方..
    【解决方案5】:

    只需始终执行RequestAdditionalTime,以您希望服务关闭所需的最长时间。提前完成并不是错误。

    【讨论】:

    • 服务流程数据基于接收到的数据,大小未知,所以我不知道需要多长时间才能停止。它不应该在处理所有数据之前停止
    • 是的,应该。接收到的数据应存储在磁盘上的队列中(因此如果断电,则不会丢失任何内容)并从那里进行处理。我停止服务的主要原因是 a) 重新启动(我想快速解决这个问题),以及 b) 如果服务出现故障(在这种情况下,我当然不希望它处理剩余的请求)。
    猜你喜欢
    • 2017-02-12
    • 2017-10-21
    • 2020-10-17
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多