一般在Windows service中,都是在OnStart方法中,启用一个新的线程去完成一些定时的任务。有时候定时任务是通过一个死循环以及线程睡眠来达到隔一段时间执行一次的效果。如下,任务1秒钟执行一次。
private bool _signal = true;
public void OnStart()
{
Task.Factory.StartNew(() =>
{
while (_signal)
{
// xxx 执行指定的业务逻辑
Thread.Sleep(1000 );
}
});
}
public void OnStop()
{
_signal = false;
}
在Windows Service启动的时候,会调用Start方法,因为signal 的默认值是true,所以在启动一个新线程之后,会进入一个死循环,一秒钟执行一次。在关闭Windows service的时候,会调用Stop方法,把signal设置为false,这样进入到下一个循环的时候,就会跳出循环,整个业务线程也就结束了。如果说在业务线程刚刚准备睡眠的时候,关闭Windows service,这样业务线程会先睡眠一秒钟,然后再进入下一个循环,这样Windows service就会等一秒钟才能关闭。
如果业务线程是1小时执行一次呢,那么这个Thread.Sleep方法就要睡眠1小时,那么关闭Windows service的时候,最多就要等一个小时,这样肯定是不行的。如何改进?我们可以自己写一个Sleep方法,如果是睡眠一个小时,我们可以把它分成睡眠很多个小段。
public bool OnStart()
{
Task.Factory.StartNew(() =>
{
while (_signal)
{
// xxx 执行指定的业务逻辑
MySleep(1000 * 60 * 15);
}
});
}
private void MySleep(double totalMillSeconds)
{
double interval = totalMillSeconds / (1000 * 60);
for (int i = 0; i < interval; ++i)
{
if (!_signal) break;
Thread.Sleep(1000 * 60);
}
}
代码中,需要睡眠15分钟,那么它每次都睡眠一分钟,每次睡眠之前,都会看一下信号变量signal,如果是false,那么就说明已经触发了关闭Windows service,那么它就会停止下一段的睡眠。这样,最多等一分钟,Windows service就会关闭。