2015-05-02 33 views
5

我有一个Windows服务,它在单独的线程上产生一组子活动,并且只应在所有这些活动都成功完成时终止。我不知道在收到停止信号后终止一个活动需要多长时间。在OnStop()期间,我会等待该停止信号的间隔,并且只要系统愿意授予它,就会继续请求额外的时间。什么是RequestAdditionalTime()的安全开销?

这里的基本结构:

class MyService : ServiceBase 
{ 
    private CancellationTokenSource stopAllActivities; 
    private CountdownEvent runningActivities; 

    protected override void OnStart(string[] args) 
    { 
     // ... start a set of activities that signal runningActivities 
     //  when they stop 
     // ... initialize runningActivities to the number of activities 
    } 

    protected override void OnStop() 
    { 
     stopAllActivities.Cancel(); 

     while (!runningActivities.Wait(10000)) 
     { 
      RequestAdditionalTime(15000); // NOTE: 5000 added for overhead 
     } 
    } 
} 

到底有多少“开销”我应该在RequestAdditionalTime呼叫加入?我担心这些请求是累积的,而不是基于每次拨打RequestAdditionalTime时的时间点。如果是这种情况,增加开销可能会导致系统最终拒绝请求,因为它将来会太远。但是如果我不添加任何开销,那么我的服务可能会在它有机会请求下一块额外时间之前终止。

回答

5

This post不完全是令人鼓舞的:

MSDN文档中没有提到这一点,但它出现在RequestAdditionalTime指定的值实际上不是“额外”的时间。相反,它会替换ServicesPipeTimeout中的值。更糟糕的是,任何大于两分钟(120000毫秒)的值都会被忽略,即在两分钟内上限。

我希望情况并非如此,但我将此作为最糟糕的答案发布。

更新:该文章的作者非常友好,可以发表非常详细的回复我的评论,我已经在下面复制。

拉尔斯,简短的回答是否定的。

我想说的是,现在我意识到Windows服务应该被设计为在需要时快速启动和终止处理。作为开发人员,我们倾向于专注于处理的实现,然后将其打包并作为Windows服务提供。

但是,这确实不是设计Windows服务的正确方法。服务必须能够快速响应请求,以便不仅在管理员从服务控制台发出请求时启动和停止,而且在操作系统正在请求启动作为其启动处理的一部分或由于它正在关闭而停止时,

请考虑当Windows配置为在UPS发出电源故障时关闭时发生的情况。该服务不适合以“我需要几分钟......”来回应。

即使在执行长时间运行的处理任务时,也可以编写能够快速响应的服务来停止请求。通常,长时间运行的过程将由数据的批处理组成,并且处理应该检查是否在确保数据一致性的最小工作单元级别上请求了停止。

举个例子,我发现停止超时的第一个服务是一个涉及处理远程服务器上的通知队列的问题。处理从队列中检索通知,调用Web服务以检索与通知主题相关的数据,然后写入数据文件以供其他应用程序处理。

我实现了处理作为一个计时器驱动调用一个单一的方法。一旦该方法被调用,它将不会返回,直到队列中的所有通知都被处理完毕。我意识到这是Windows服务的错误,因为偶尔会有成千上万的通知在队列中,处理可能需要几分钟的时间。

该方法能够处理每秒50个通知。所以,我应该做的是在处理每个通知之前执行一次检查以查看是否已请求停止。这将允许该方法在完成通知处理但在开始处理下一个通知之前返回。这可以确保服务能够快速响应停止请求,并且在重新启动服务时任何待处理的通知仍然排队等待处理。