我正在遵循本教程:http://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx来创建Windows服务。我有一个名为TaskManager
的类,它使用Quartz.Net来管理一堆作业。它有.Go()
(不阻止)和.Stop()
方法。如果我理解正确,我在服务中需要做的就是
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;
属性,或者这个默认值是一个好事吗?基本上我不知道这个值是什么......
答案 0 :(得分:2)
正如@HansPassant所说
ServiceBase类已经处理服务状态的方式 在99.9%的案例中足够好。 您不应该需要它,30秒(默认值)足以获得99.9%的所有服务 启动/停止。
但是如果你需要处理一个长时间的关闭,documentation说关于
dwWaitHint
待定开始,停止所需的估计时间, 暂停或继续操作,以毫秒为单位。在指定之前 已经过了一段时间,服务应该进行下一次调用 具有递增的dwCheckPoint的SetServiceStatus函数 值或dwCurrentState的变化。如果指定的时间量 通过dwWaitHint传递,并且dwCheckPoint没有增加或 dwCurrentState没有改变,服务控制管理器或服务 控制程序可以假设发生了错误和服务 应该停止。但是,如果服务与其他服务共享进程 服务,服务控制管理器无法终止服务 应用程序,因为它必须终止其他服务 分享这个过程。
和
dwCheckPoint
服务定期递增的检查点值 在漫长的开始,停止,暂停或 继续运作。例如,服务应该增加此值 值,因为它完成初始化的每一步 启动。调用操作的用户界面程序 该服务使用此值来跟踪服务的进度 在漫长的操作中。该值无效,应为零 当服务没有开始,停止,暂停或继续时 正在进行中
这澄清了walk-through中的脚注。
服务控制管理器使用dwWaitHint和dwCheckpoint SERVICE_STATUS结构的成员确定要花多少时间 等待Windows服务启动或关闭。如果您的OnStart和 OnStop方法运行时间长,您的服务可以通过调用请求更多时间 再次使用递增的dwCheckPoint值SetServiceStatus。
基于此,我写了这样的Stop代码。请注意,我运行一些非常长的任务并且终止它们实际上并不是一个好主意,因此漫长的等待时间。
//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);
}