我希望每隔10秒从Windows服务(使用C#和.NET完成)调用Business层方法。但是,我不想使用Timer_Elapsed事件,因为如果第一个线程/进程仍在运行,它将启动另一个线程/进程。我只需要一个单线程方法,因为对同一个Business方法的多次调用会产生不必要的复杂情况。
所以我在on_start中添加了一个do-while循环。我知道这不是正确的方法,因为它会产生这个过程,如果服务被关闭,它就会成为一个孤儿。
我如何解决这个问题?
此致 泽
答案 0 :(得分:45)
还有另一种获取定时执行的方法,WaitHandle.WaitOne()方法提供了一个超时参数。这在服务中非常有效,因为它允许您在单个方法调用中实现停止服务和定期执行的需要。模板看起来像这样:
Thread Worker;
AutoResetEvent StopRequest = new AutoResetEvent(false);
protected override void OnStart(string[] args) {
// Start the worker thread
Worker = new Thread(DoWork);
Worker.Start();
}
protected override void OnStop() {
// Signal worker to stop and wait until it does
StopRequest.Set();
Worker.Join();
}
private void DoWork(object arg) {
// Worker thread loop
for (;;) {
// Run this code once every 10 seconds or stop right away if the service
// is stopped
if (StopRequest.WaitOne(10000)) return;
// Do work...
//...
}
}
答案 1 :(得分:4)
使用计时器,但只要输入Timer处理程序方法,就禁用计时器,以便不再引发事件。在退出处理程序之前,重新启用计时器。
答案 2 :(得分:4)
查看this discussion,特别是jsw的回答。它建议了一种同步机制,以防止多次同时调用业务逻辑。由于在单独的线程上调用处理程序,因此无法保证在Elapsed
处理程序方法中禁用计时器会阻止并行调用。使用jsw建议的锁定,并在同步代码块中停止计时器。
或者,您可以使用Timer
并将AutoReset
属性设置为false
。这样,Elapsed
事件只会被引发一次,您可以在处理程序方法结束时手动重置计时器。
答案 3 :(得分:-2)
while(true)
{
..do something
Thread.sleep( some time or day);
}
答案 4 :(得分:-2)
Thread thread;
private void DoWork(object arg)
{
while (true)
{
// Run this code once every 20 seconds or stop if the service is stopped
try
{
Thread.Sleep(20000);
//Do work....
}
catch(ThreadInterruptedException)
{
return;
}
}
}
protected override void OnStart(string[] args)
{
// Start the thread
thread = new Thread(DoWork);
mWorker.Start();
}
protected override void OnStop()
{
// interrupt thread and wait until it does
thread.Interrupt();
thread.Join();
}