c# - 如果前一个线程仍然很忙,如何让 Timer 跳过滴答

标签 c# multithreading windows-services timer

我创建了一个 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/

相关文章:

c# - 如何使用 app.config 将 Azure Key Vault 连接到 C# Windows 服务

.net - 适用于 WCF Windows 服务的 Amazon EC2

c# - .Net Core 2.2 Web API 在 GET 上获取 415 不支持的媒体类型?

c# - 四舍五入小数

c# - 如何在 Razor 中修复此 "syntax error"?

c++ - boost asio 在线程中运行 io_service

python - 如果线程处于无限 while 循环中,会发生什么情况?

c# - 使用 WCF 的 Windows 服务

c# - 如何在asp.net中的下拉列表中绑定(bind)数据库中的选定值

c# - 为并发 C# 代码编写单元测试?