如果前一个线程仍然繁忙,如何让计时器跳过刻度

2024-03-15

我创建了一个 Windows 服务,该服务应该每 60 秒检查数据库中的某个表是否有新行。对于添加的每个新行,我都需要在服务器上进行一些繁重的处理,有时可能需要 60 秒以上的时间。

我在服务中创建了一个 Timer 对象,该对象每 60 秒计时一次并调用所需的方法。
由于我不希望这个计时器在处理找到的新行时滴答作响,因此我将该方法包装在lock { }块,因此其他线程无法访问它。

它看起来像这样:

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 秒,则下一个滴答不会执行任何处理,直到前一个滴答完成。这就是我想要的效果。

但现在,服务 Timer Elapsed 方法是在第一次处理完成后立即关闭,还是等待计时器再次计时。

我想要发生的是 - 如果处理需要超过 60 秒,那么计时器会注意到线程被锁定,并再等待 60 秒再次检查,这样我就永远不会陷入有线程队列的情况等待上一个完成。

我怎样才能实现这个结果?
这样做的最佳实践是什么?

Thanks!


您可以尝试在处理过程中禁用计时器,例如

// 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(); 
}

Edit:OP没有指定重入是否仅由计时器引起,或者服务是否是多线程的。假设是后者,但如果是前者,那么如果计时器停止(自动重置或手动),则锁定应该是不必要的

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果前一个线程仍然繁忙,如何让计时器跳过刻度 的相关文章

随机推荐