我创建了一个 Windows 服务,它应该每 60 秒检查数据库中的某个表是否有新行。对于添加的每一行,我都需要在服务器上进行一些繁重的处理,有时可能需要超过 60 秒。
我在我的服务中创建了一个 Timer 对象,它每 60 秒计时一次并调用所需的方法。
由于我不希望此计时器在处理找到的新行时计时,我将该方法包装在 lock { }
block 中,因此其他线程无法访问它。
看起来像这样:
Timer serviceTimer = new Timer();
serviceTimer.Interval = 60;
serviceTimer.Elapsed += new ElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (this)
{
// do some heavy processing...
}
}
现在,我想知道-
如果我的计时器滴答作响,并在数据库中发现很多新行,现在处理时间将超过 60 秒,下一个滴答将不会进行任何处理,直到前一个滴答完成。这就是我想要的效果。
但是现在,serviceTimer_Elapsed 方法会在第一个处理完成后立即关闭,还是会等待计时器再次计时。
我想要发生的是 - 如果处理需要超过 60 秒,那么计时器会注意到线程已锁定,然后再等 60 秒再次检查,这样我就不会陷入有等待前一个线程完成的线程队列。
我怎样才能达到这个结果?
这样做的最佳做法是什么?
谢谢!
最佳答案
你可以尝试在处理过程中禁用定时器,比如
// Just in case someone wants to inherit your class and lock it as well ...
private static object _padlock = new object();
try
{
serviceTimer.Stop();
lock (_padlock)
{
// do some heavy processing...
}
}
finally
{
serviceTimer.Start();
}
编辑 : OP 没有说明重入是仅由定时器引起的还是服务是多线程的。假设是后者,但如果是前者,那么如果计时器停止(自动重置或手动),则不需要锁定
关于c# - 如果前一个线程仍然很忙,如何让 Timer 跳过滴答,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3424907/