首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >同步计时器以防止重叠

同步计时器以防止重叠
EN

Stack Overflow用户
提问于 2009-03-26 01:33:32
回答 4查看 23K关注 0票数 25

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

我如何简单地设置一个计时器来每30秒运行一次任务,同时又不会重叠执行?(我假设System.Threading.Timer是这项工作的正确计时器,但也可能是错误的)。

EN

回答 4

Stack Overflow用户

发布于 2009-03-26 01:43:59

我会在你的代码中使用Monitor.TryEnter:

代码语言:javascript
复制
if (Monitor.TryEnter(lockobj))
{
  try
  {
    // we got the lock, do your work
  }
  finally
  {
     Monitor.Exit(lockobj);
  }
}
else
{
  // another elapsed has the lock
}
票数 29
EN

Stack Overflow用户

发布于 2009-03-26 03:48:38

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

代码语言:javascript
复制
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.
    }
}

您可以通过将计时器设置为一次性计时器并在每次更新后重新启动它来消除对锁的需求:

代码语言:javascript
复制
// 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);
}
票数 19
EN

Stack Overflow用户

发布于 2009-03-26 03:24:25

而不是锁定(这可能会导致所有定时扫描等待并最终堆叠)。您可以在线程中启动扫描/更新,然后执行检查以查看该线程是否仍处于活动状态。

代码语言:javascript
复制
Thread updateDBThread = new Thread(MyUpdateMethod);

..。

代码语言:javascript
复制
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    if(!updateDBThread.IsAlive)
        updateDBThread.Start();
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/684200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档