【发布时间】:2008-12-01 23:55:21
【问题描述】:
假设我有一个现有的 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)),如果原始计时器触发,则通过在回调中检查 DateTime.Now 来忽略它。 (我担心这可能不是 100% 可靠,因为使用 TimeSpan 的 Timer 和使用 DateTime 的检查......这可能不是问题,但由于某种原因我对它并不完全满意...... )
我的问题是:
- 有没有一种好方法可以让我调用 Timer.Change 并能够知道在回调排队到线程池之前我是否设法更改它? (我不这么认为,但问起来也无妨……)
- 有没有其他人实施过(我称之为)这样的“后推计时器”?如果是这样,我很想听听您是如何解决这个问题的。
这个问题本质上是假设性的,因为我已经有几个可行的解决方案(基于 Dispose 和基于 DateTime.Now)...我主要对听取与性能相关的建议感兴趣(因为我将非常频繁地“推回”计时器)。
谢谢!
【问题讨论】: