2011-03-16 23 views
1

我碰到一些代码,迷迷糊糊类似如下:正确使用System.Threading.Timer

private void SomeCallBack(object state) 
    { 
     lock (_lock) 
     { 
      try 
      { 
       if (_timer == null) 
        return; 

       _timer.Dispose(); 
       // do some work here 
      } 
      catch 
      { 
       // handle exception 
      } 
      finally 
      { 
       _timer = new Timer(SomeCallBack, state, 100, Timeout.Infinite); 
      } 
     } 
    } 

我不明白,每次执行回调时重建定时器的目的。我认为代码试图实现的是一次只有一个线程可以执行这项工作。但是这个锁是否足够?

此外,根据MSDN,

注意,可以在Dispose()方法重载后出现回调,被称为

是否有这样做有什么好处? 如果是这样,那么在处置和创建计时器时,这些好处是否合理呢?

感谢您的帮助。

回答

1

看起来代码想要一个接近周期的定时器(由于定时器到期和创建新定时器之间的处理引入了抖动,所以不完全是周期性的)。处理和重新创建定时器确实是不必要的开销。 Change方法会更好。

对null的检查也很好奇;在其他地方,必须有代码将_timer设置为null才能起作用。

+0

定时器在函数中设置为null以停止定时器。如果你只是将间隔设置为100就不会达到同样的效果?你甚至不需要使用'Change()'。状态在函数中没有修改,所以重新创建定时器的目的不是为实际工作传递新的参数。 – zyq

+0

这个答案是正确的。该代码正在创建一个一次性定时器。结果是一个回调结束和下一个回调开始之间会有100 ms的延迟。但是由于该时间段设置为'Timeout.Infinite',所以定时器不会再次启动。通过调用'_timer.Change(100,Timeout.Infinite)'可以达到同样的效果,只是它不能处理定时器为'null'的情况。在现有的代码中,如果定时器为空,则不进行处理,但在“finally”中创建新的定时器。 –

+0

此外,在这里使用锁是很好奇的。除非有多个使用此回调的定时器,否则它们将无法同时被多个线程调用。定时器是一次性的,使得重入电话成为不可能。 –

0

重新创建定时器的原因是定时器回调中的代码比定时器周期执行需要更长的时间。在这种情况下,回调的多个实例将同时运行。