在其Calback正在进行时禁用System.Threading.Timer实例

时间:2013-06-01 07:18:20

标签: multithreading c#-4.0 timer

我正在使用System.Threading.Timer的两个实例来触发定期重复的2个任务。

我的问题是:如果计时器被禁用但在此时间点此计时器正在线程上执行其回调,那么Main方法将退出或者它将等待执行的回调到完成?

在下面的代码中,Method1RunCount使用lock语句进行读写同步(这部分代码未在下面显示)。对于timer1的回调,在每次运行结束时将Method1RunCount递增1。

static void Main(string[] args)
{
    TimerCallback callback1 = Method1;
    System.Threading.Timer timer1 = new System.Threading.Timer(callback1,null,0, 90000);
    TimerCallback callback2 = Method2;
    System.Threading.Timer timer2 = new System.Threading.Timer(callback2, null, 0, 60000);
    while (true)
    {
         System.Threading.Thread.Sleep(250);
         if (Method1RunCount == 4)
         {
              //DISABLE the  TIMERS
              timer1.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
              timer2.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
              break;
         }
     }
 }

2 个答案:

答案 0 :(得分:2)

这种代码往往是偶然的,定时器的周期足够大,以避免Method1RunCount变量上的线程竞争。缩短期限,主要线程不会看到价值" 4"一点都不当处理器负载很重且主线程没有安排好时,可能性会大大降低。然后,当主线程正在等待处理器时,计时器的回调可以执行多次。完成丢失值增加到4.注意 lock 语句实际上不会阻止它,它不会被主线程锁定,因为它可能正在睡眠。

对于Method2运行的频率,您也无法做出合理的猜测。不仅因为它具有完全不同的计时器周期,而且基本上是因为它根本不与Method1或Main方法执行同步。

您通常会在Method1的 end 处增加Method1RunCount。但这并不能保证Method1不会被中止。它在线程池线程上运行,它们的Thread.IsBackground属性始终设置为true。因此,当主线程退出时,CLR将很快中止它们。这也不会偶然导致问题。

如果Method1执行正好4次绝对必要,那么确保这样做的简单方法就是让Method1进行计数。在方法中调用Timer.Change()很好。使用类似AutoResetEvent的类让主线程知道它。现在不再需要睡眠了。您仍需要锁定以确保在执行时无法重新输入Method1。当你看到自己使用Thread.Sleep()时,知道你正在获得错误的线程同步的好方法。

答案 1 :(得分:0)

来自System.Threading.Timerhttp://msdn.microsoft.com/en-us/library/system.threading.timer.aspx)上的文档:

  

当不再需要计时器时,使用Dispose方法释放   计时器持有的资源。请注意,回调可能发生在   已调用Dispose()方法重载,因为定时器队列   线程池线程执行的回调。你可以使用   Dispose(WaitHandle)方法重载等待直到所有回调都有   完成。