2014-10-07 107 views
2

我在关注本教程:http://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx来创建一个Windows服务。我有一个名为TaskManager的课程,它使用Quartz.Net来管理一堆作业。它有.Go()(不阻止)和.Stop()方法。如果我的理解正确,我所需要做的就是我的服务如何为serviceStatus.dwWaitHint选择值?

private TaskManager _taskManager; 

    public DataPumpService() 
    { 
     InitializeComponent(); 
     _taskManager = new TaskManager(); 
    } 

    protected override void OnStart(string[] args) 
    { 
     _taskManager.Go(); 
    } 

    protected override void OnStop() 
    { 
     _taskManager.Stop(); 
    } 

但是接下来教程有一个关于设置服务状态的部分。它并没有真正解释服务状态是什么,或者当我想要设置它。 TaskManager.Stop()可能需要几秒钟才能完成(在内部,它在所有作业上调用IScheduler.Interrupt(),然后调用IScheduler.Shutdown(true))。那么我应该设置状态?如果是这样,假设我在the tutorial的设置服务状态部分的(1),(2)和(3)部分中包含代码,那么是否正确执行以下操作(基本上用于上述第一个代码块中的两种方法):

protected override void OnStop() 
    { 
     // Update the service state to Stop Pending. 
     ServiceStatus serviceStatus = new ServiceStatus(); 
     serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING; 
     serviceStatus.dwWaitHint = 100000; 
     SetServiceStatus(this.ServiceHandle, ref serviceStatus); 

     _taskManager.Stop(); 

     // Update the service state to Running. 
     serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; 
     SetServiceStatus(this.ServiceHandle, ref serviceStatus); 
    } 

如果这是正确的,那么是serviceStatus.dwWaitHint = 100000;性质的东西,我需要做出明智的选择或者是默认值,坚持一件好事吗?基本上我不知道这个值是...

+1

嗯,不知道它是如何进入该MSDN文章。在99.9%的案例中,ServiceBase类已经处理好服务状态的方式已经足够。包含此dwWaitHint,它由ServiceBase.RequestAdditionalTime()方法包装。你不应该需要它,30秒就足以让99.9%的所有服务开始:)请注意,4.5之前的这篇文章的版本都没有谈及它。 – 2014-10-07 20:11:37

+0

@HansPassant所以你是说如果我只是使用我的第一块代码,不要惹恼serviceStatus - 它通常很好?你什么意思30秒...是默认还是你建议我使用30000而不是100000? – Dan 2014-10-07 21:29:07

+2

不要惹它。 30秒是Windows使用的默认超时。 – 2014-10-07 21:32:10

回答

2

由于@HansPassant

ServiceBase类已经采取的服务状态 护理的方法是在的情况下,99.9%的不够好。 您不应该需要它,30秒(默认值)足以让99.9%的所有服务 开始/停止。

但是,如果你需要处理一个长时间运行结束时,documentation说,关于

dwWaitHint

对于一个挂起启动时所需的估计时间,停止, 暂停或继续操作,以毫秒为单位。在指定的 时间量已过之前,该服务应使用递增的dwCheckPoint 值或dwCurrentState中的更改,对SetServiceStatus函数进行下一次调用 。如果dwWaitHint通过指定的 的时间量,并且dwCheckPoint尚未增加或 dwCurrentState未更改,则服务控制管理器或服务控制程序可以假定发生了错误并且应该停止服务 。但是,如果服务与其他服务共享一个进程,则服务控制管理器无法终止服务 应用程序,因为它必须终止共享该进程的其他服务 。

dwCheckPoint

的检查点值的服务增量定期 到一个漫长的启动过程中报告其进度,停止,暂停,或 继续操作。例如,该服务应该在 启动时完成其初始化的每个步骤时递增此值 值。调用 上的操作的用户界面程序在长时间操作期间使用该值来跟踪服务 的进度。当服务没有启动,停止,暂停或继续 操作未决时,此值无效并应为零。 。

这说明了walk-through中的脚注。

服务控制管理器使用SERVICE_STATUS结构的dwWaitHint和dwCheckpoint 成员多少时间来确定 等待Windows服务来启动或关闭。如果OnStart和OnStop方法运行时间很长,则可以通过使用递增的dwCheckPoint值再次调用 SetServiceStatus来请求更多时间。

基于此,我编写了像这样的停止代码。请注意,我执行一些非常长的任务并终止它们实在不是一个好主意,因此漫长的等待时间。

//set the status to pending close 
var serviceStatus = new ServiceStatus 
{ 
    dwCurrentState = ServiceState.SERVICE_STOP_PENDING, 
    dwWaitHint = 120000//two minutes wait time 
}; 
SetServiceStatus(this.ServiceHandle, ref serviceStatus); 

Engine.Cancel(); 

while (Engine.IsRunning()) 
{ 
    System.Threading.Thread.Sleep(1000); 
    serviceStatus.dwCheckPoint++;//updating the checkpoint so I don't get terminated 
    SetServiceStatus(this.ServiceHandle, ref serviceStatus); 
} 
+0

谢谢,如果您在此答案的顶部添加了一个部分,指定Hans Passant在评论中所说的内容,即在99.9%的情况下您应该保留默认值,我很乐意接受这一点。 – Dan 2016-07-20 07:10:04

+0

已添加。谢谢。它实际上使它更好。 – frostymarvelous 2016-07-20 11:07:33