监控,锁定还是挥发?

时间:2013-06-24 09:07:33

标签: c# .net multithreading

我有一个Windows服务(.NET 4)定期处理队列,例如每15分钟一次。我使用System.Threading.Timer,当服务开始每X毫秒触发一次回调时设置{{1}}。通常每次运行需要几秒钟而且永远不会发生冲突,但如果我不能假设那么 - 那么如果处理正在进行中,我希望下一次运行立即退出。

这可以通过锁定,易失性bool或监视器轻松解决,但实际上在这种情况下使用的是什么,或者只是一般的首选选项?

我发现其他帖子几乎可以回答这种情况(例如Volatile vs. Interlocked vs. lock),但需要一些建议,将其扩展到Timer示例并立即退出。

3 个答案:

答案 0 :(得分:6)

您不需要任何锁定,您应该从计时器委托中重新安排下一个计时器执行。这应该确保100%没有重叠。

在计时器的事件处理程序调用{​​{1}}结束时,计时器将在timer.Change(nextRunInMilliseconds, Timeout.Infinite)之后仅触发一次。

示例:

nextRunInMilliseconds

答案 1 :(得分:1)

好吧,他们中的任何一个都能胜任这项工作。 Monitor 通常通过lock非常简单,但在这种情况下你不能使用lock,因为你需要指定零超时;因此,最简单的方法可能是CompareExchange

private int isRunning;
...
if(Interlocked.CompareExchange(ref isRunning, 1, 0) == 0) {
    try {
        // your work
    } finally {
        Interlocked.Exchange(ref isRunning, 0);
    }
}

Monitor做同样的事情是:

private readonly object syncLock = new object();
...
bool lockTaken = false;
try {
    Monitor.TryEnter(syncLock, 0, ref lockTaken);
    if (lockTaken) {
        // your work
    }
} finally {
    if(lockTaken) Monitor.Exit(syncLock);
}

答案 2 :(得分:0)

我认为,如果您发现需要同步计时器委托 - 您做错了,Timer可能不是您要使用的类。 Imho更好:

1)要么保留Timer,要么将间隔值增加到可以安全假设的点,即线程没有问题,

2)或删除Timer并使用简单的线程代替。你知道,比如:

var t = new Thread();
t.Start(() =>
         {
            while (!_stopEvent.WaitOne(100))
            {
                 ..........
            }
         });
相关问题