Windows服务是否需要花费数小时才能优雅地关闭?

8
我们有一个.NET Windows服务,以事务方式从A传输大量高度关键的数据到B。我们还需要确保服务中使用的所有外部组件都正确释放,并在关闭服务本身之前清理一切。这可能需要几个小时!原因是服务需要等待外部组件的回调,这些回调会在2、3或4个小时后到达。
  1. Windows是否可以等待服务正常关闭如此长的时间?
  2. 在服务被操作系统关闭时,我能否在服务中指定发生的情况,例如完全阻止关闭?
  3. 另外,如果服务器需要重新启动,会发生什么?它能等待服务数小时吗?
  4. 操作系统在杀死服务之前会等待多长时间?

6
你忘记了:5.一个人等待机器正常关机的时间是否有限制?超过限制会直接拔掉电源吗? - Hans Kesting
3个回答

8

你可以使用 CanStop, CanShutdown, CanHandlePowerEvent 来接收计算机正在关闭的通知并做出相应的响应。

使用 ServiceBase.RequestAdditionalTime 方法请求额外的时间来终止线程:

protected override void OnShutdown() 
{
    base.RequestAdditionalTime(MaxTimeout);
    serviceCore.OnShutdown();
    Stop(); 
}

如果您的OnShutdown()阻塞时间超过20秒(默认值存储在注册表HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ WaitToKillServiceTimeout中),则您的服务将被标记为无响应并被终止。 这里有一篇来自BCL团队的很好的博客文章,我推荐阅读。

4
OnShutdown 中调用 RequestAdditionalTime 会导致 InvalidOperationException - Peter Ritchie

4

是的,一个服务可以在完成之前停止关闭,但是它应该这样做吗?在注册表中有超时值,操作系统是什么?

我认为你需要将回调与其他组件分离,或者将数据缓冲到磁盘并发送更小的片段。如果发生停电怎么办?或者如果有人等得不耐烦,关掉了电源怎么办?

如果数据很重要,请在内存外管理它,并使进程可重新启动。这将解决您冗长的关闭过程。同样,一种轮询组件进度的方法可以消除阻塞的依赖。


是的,数据在某种程度上非常关键。这是一个企业级应用程序,需要移动、解析和索引大量数据。问题在于组件运行缓慢。任何时候都可能有多达20,000个回调等待发生,这也是导致速度缓慢的部分原因。轮询不是选项,因为其API不允许我们这样做。 - John
这很混乱,每个调用肯定不需要几个小时吧?你能使用更小的批次,并将调用分布在多台机器上吗? - TheCodeKing

1
在OnShutdown()中不能使用RequestAdditionalTime(MaxTimeout)...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接