假设我有一个现有的System.Threading.Timer实例,我想调用它上面的Change来推动它的触发时间:
var timer = new Timer(DelayCallback, null, 10000, Timeout.Infinite); // ... (sometime later but before DelayCallback has executed) timer.Change(20000, Timeout.Infinite);
我正在使用这个计时器在一段时间没有活动后执行"空闲回调".(在这种情况下,"空闲"和"无活动"是应用程序定义的条件......具体情况并不十分重要.)每次执行"操作"时,我都想重置计时器,以便始终设置在那之后10秒开火.
但是,存在固有的竞争条件,因为当我调用Change时,我无法判断Timer是否已根据其旧设置触发.(当然,我可以告诉我的回调是否已经发生,但我无法判断CLR的内部计时器线程是否已将我的回调排队到线程池并且其执行即将发生.)
现在我知道我可以在计时器实例上调用Dispose,并在每次需要"推回"时重新创建它.但这似乎不仅仅是改变现有的计时器.当然可能不是......我会稍微运行一些微基准测试,让大家都知道.
或者,我总是可以跟踪预期的触发时间(通过DateTime.Now.AddSeconds(10)),如果原始Timer触发,则通过检查回调中的DateTime.Now来忽略它.(我有一个唠叨的担心,由于使用TimeSpan的Timer和我使用DateTime的检查,这可能不是100%可靠...这可能不是问题,但由于某种原因我不是完全适应它... )
我的问题是:
有没有一个好方法让我调用Timer.Change并能够知道我是否设法在回调排队到线程池之前更改它?(我不这么认为,但要求......并没有坏处.)
有没有其他人实现(我称之为)这样的"后推计时器"?如果是这样,我很想知道你是如何解决这个问题的.
这个问题在某种程度上是假设性的,因为我已经有了几个工作解决方案(基于Dispose并基于DateTime.Now)......我主要对听到与性能相关的建议感兴趣(因为我将"推回" "非常频繁的计时器".
谢谢!