gil*_*lyb 14 c# multithreading windows-services timer
我创建了一个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秒,下一个滴答将不会进行任何处理,直到前一个完成.这就是我想要的效果.
但现在,serviceTimer_Elapsed方法会在第一次处理完成后立即关闭,还是会等待计时器再次打勾.
我想要发生的是 - 如果处理需要超过60秒,那么计时器会注意到线程被锁定,再等待60秒再次检查,这样我就永远不会陷入有线程队列的情况等待前一个完成.
我怎样才能完成这个结果?
这样做的最佳做法是什么?
谢谢!
Stu*_*tLC 21
您可以尝试在处理期间禁用计时器,例如
// 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没有指定重入是否仅由计时器引起或者服务是否是多线程的.假设后者,但如果前者然后锁定应该是不必要的,如果计时器停止(AutoReset或手动)
Ani*_*Ani 20
在这种情况下,您不需要锁.在启动之前设置timer.AutoReset = false.完成处理后,在处理程序中重新启动计时器.这将确保计时器在每个任务后 60秒触发.
快速检查它是否正在运行.如果它正在运行,它将跳过此事件并等待下一个事件触发.
Timer serviceTimer = new Timer();
serviceTimer.Interval = 60;
serviceTimer.Elapsed += new ElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();
bool isRunning = false;
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    lock (this)
    {
        if(isRunning)
            return;
        isRunning = true;
    }
    try
    {
    // do some heavy processing...
    }
    finally
    {
        isRunning = false;
    }
}
其他答案的类似变化,允许计时器保持滴答,只有在可以获得锁定时才能完成工作,而不是停止计时器.
把它放在经过的事件处理程序中:
if (Monitor.TryEnter(locker)
{
    try
    {
        // Do your work here.
    }
    finally
    {
        Monitor.Exit(locker);
    }
}
| 归档时间: | 
 | 
| 查看次数: | 17538 次 | 
| 最近记录: |