我想用a 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
确定性清理创建一次性计时器?
(创建一次性定时器/延迟的更好方法超出了这个问题的范围.我故意以特定方式询问这一点.)
更改为Timer的构造函数,该构造函数仅接收回调,以便它将自己传递给state参数.用于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
参数,您也可以使用闭包变量,就像问题中的代码一样.关键是没有使用构造函数启动计时器.只有在存储了对定时器的引用后才启动它.