当前位置:  开发笔记 > 编程语言 > 正文

同步计时器以防止重叠

如何解决《同步计时器以防止重叠》经验,为你挑选了3个好方法。

我正在编写一个Windows服务,每隔一段时间运行一次可变长度的活动(数据库扫描和更新).我需要经常运行此任务,但要处理的代码并不安全地同时运行多次.

我怎样才能最简单地设置一个计时器来每隔30秒运行一次任务,而不会重复执行?(我假设System.Threading.Timer这个工作是正确的计时器,但可能会弄错).



1> Reed Copsey..:

您可以使用Timer执行此操作,但您需要在数据库扫描和更新时使用某种形式的锁定.简单lock的同步可能足以防止发生多次运行.

话虽如此,在操作完成后启动计时器可能会更好,只需使用一次,然后停止它.在下一次操作后重新启动它.这将在事件之间给你30秒(或N秒),没有重叠的可能性,也没有锁定.

示例:

System.Threading.Timer timer = null;

timer = new System.Threading.Timer((g) =>
  {
      Console.WriteLine(1); //do whatever

      timer.Change(5000, Timeout.Infinite);
  }, null, 0, Timeout.Infinite);

立即工作.....完成......等待5秒....立即工作.....完成......等待5秒....


我是第三种方法.您还可以动态计算定时器延迟以接近30秒.禁用计时器,获取系统时间,更新数据库,然后初始化下一个计时器以在保存时间后30秒触发.具有最小的定时器延迟以确保安全.
我采用这种方法 - '在你的操作完成后启动计时器可能会更好......'

2> jsw..:

我在你已用完的代码中使用了Monitor.TryEnter:

if (Monitor.TryEnter(lockobj))
{
  try
  {
    // we got the lock, do your work
  }
  finally
  {
     Monitor.Exit(lockobj);
  }
}
else
{
  // another elapsed has the lock
}



3> Jim Mischel..:

我喜欢这样System.Threading.Timer的事情,因为我不需要经历事件处理机制:

Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, 30000);

object updateLock = new object();
void UpdateCallback(object state)
{
    if (Monitor.TryEnter(updateLock))
    {
        try
        {
            // do stuff here
        }
        finally
        {
            Monitor.Exit(updateLock);
        }
    }
    else
    {
        // previous timer tick took too long.
        // so do nothing this time through.
    }
}

您可以通过使计时器一次性完成并在每次更新后重新启动它来消除锁定的需要:

// Initialize timer as a one-shot
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, Timeout.Infinite);

void UpdateCallback(object state)
{
    // do stuff here
    // re-enable the timer
    UpdateTimer.Change(30000, Timeout.Infinite);
}

推荐阅读
小妖694_807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有