C# 停机联锁保护例行程序

C# 停机联锁保护例行程序,c#,C#,我的计时器例程受多入口保护,如下所示: private void TimerCallback(object state) { if (Interlocked.CompareExchange(ref currentlyRunningTasksCount, 1, 0) != 0) { return; } // some job is being done here Interlocked.Decrement(ref currentlyRun

我的计时器例程受多入口保护,如下所示:

private void TimerCallback(object state)
{
    if (Interlocked.CompareExchange(ref currentlyRunningTasksCount, 1, 0) != 0)
    {
        return;
    }

    // some job is being done here

    Interlocked.Decrement(ref currentlyRunningTasksCount);
}
<>也有定时器关机程序,我想确保计时器不在某个中间。因此,我做了以下工作:

public void Shutdown()
{
    aTimer.Change(Timeout.Infinite, Timeout.Infinite);
    for(;;)
    {
        if (Interlocked.CompareExchange(ref currentlyRunningTasksCount, 0, 0) == 0)
        {
            break;
        }
        else
        {
            Thread.Sleep(1000);
            continue;
        }
    }
}

问题-检查关机是否正确,或者我应该使用
联锁。阅读
并与0比较?

我会使用锁。它可以轻松地支持这两种情况,无需等待

如果(!Monitor.TryEnter(…)返回,则可以使用
退出勾号处理程序

要等待计时器退出,请执行
锁定(…){}

您需要设置一个布尔字段来表示计时器已关闭。调用
Change
后,可以触发任意多个勾号事件。(出于同样的原因,您现有的
关闭
代码实际上并没有关闭计时器。)

尽管如此,所有这些都可以简化:

async Task RunMyTimerAgent() {
    while (true) {
     await Task.Delay(...);
     Work();
     ThrowIfCancelled();
    }
}

var timer = RunMyTimerAgent();
//cancel the timer here
timer.Wait(); //Wait till shutdown.

不过,这个循环有时间漂移。

lock
更容易理解。。。此外,创建能够被最少人阅读/理解的代码可能是OP的全部要点:)。顺便说一句,我认为在
任务的循环中。延迟
对于固定时间漂移来说更为明显,因为人们可以每次调整延迟(不像通常以固定延迟和漂移运行的常规计时器)。对不起,
应该取代什么?当前关闭程序?你能详细说明一下这个机制吗?while会取代整个定时器。如何修正漂移?我觉得这种方法非常简单有趣。@ScottChamberlain我推荐TickCount。DateTime.UtcNow可以任意更改,并导致循环基本停止或提前执行。微软推动在BCL中用UtcNow替换各种内部超时。我想它发生在4.5。