我想使用System.Threading.Timer
执行一次。一旦不再需要(即回调触发时),就应该通过调用Dispose
来确定性地清理该计时器。
问题是回调无法可靠地获得对Timer
的引用!
System.Threading.Timer timer = null;
timer = new System.Threading.Timer(_ =>
{
Console.WriteLine("Elapsed.");
//Dispose the timer here, but timer might be null!
timer.Dispose(); //BUG
}, null, TimeSpan.FromSeconds(1), TimeSpan.Zero);
当回调触发时,可能不会初始化变量timer
。此代码在所有情况下都不起作用,因为它包含竞争条件。
我们如何使用System.Threading.Timer
创建具有确定性清理的一次性计时器?
(创建一次性定时器/延迟的更好方法超出了这个问题的范围。我故意以特定方式询问这一点。)
答案 0 :(得分:5)
更改为仅接收回调的constructor of Timer,以便在状态参数中自行传递。之后立即使用Change()
进行设置:
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((state) =>
{
Console.WriteLine("Elapsed.");
// Dispose of the timer here:
((System.Threading.Timer)state).Dispose();
});
timer.Change(TimeSpan.FromSeconds(1), TimeSpan.Zero);
如果您不想使用state
参数,您也可以使用闭包变量,就像问题中的代码一样。关键是没有使用构造函数启动计时器。只有在存储了对定时器的引用后才启动它。