c#中的定时器初始化和竞争条件?

Roy*_*mir 7 c# multithreading timer .net-4.0

我在里希特的书上看到了这段代码:

下面的代码演示了如何让线程池线程调用立即启动的方法,然后每隔2秒调用一次:

/*1*/    internal static class TimerDemo
/*2*/    {
/*3*/        private static Timer s_timer;
/*4*/        public static void Main()
/*5*/        {
/*6*/            Console.WriteLine("Checking status every 2 seconds");
/*7*/            // Create the Timer ensuring that it never fires. This ensures that
/*8*/            // s_timer refers to it BEFORE Status is invoked by a thread pool thread
/*9*/            s_timer = new Timer(Status, null, Timeout.Infinite, Timeout.Infinite);
/*10*/            // Now that s_timer is assigned to, we can let the timer fire knowing
/*11*/            // that calling Change in Status will not throw a NullReferenceException
/*12*/            s_timer.Change(0, Timeout.Infinite);
/*13*/            Console.ReadLine(); // Prevent the process from terminating
/*14*/        }
/*15*/        // This method's signature must match the TimerCallback delegate
/*16*/        private static void Status(Object state)
/*17*/        {
/*18*/            // This method is executed by a thread pool thread
/*20*/            Console.WriteLine("In Status at {0}", DateTime.Now);
/*21*/            Thread.Sleep(1000); // Simulates other work (1 second)
/*22*/            // Just before returning, have the Timer fire again in 2 seconds
/*23*/            s_timer.Change(2000, Timeout.Infinite);
/*24*/            // When this method returns, the thread goes back
/*25*/            // to the pool and waits for another work item
/*26*/        }
/*27*/    }
Run Code Online (Sandbox Code Playgroud)

但是,(对不起),我还是不明白什么行#7,#8意味着什么

当然 - 为什么它被初始化(第9行)Timeout.Infinite(很明显:" 不要启动计时器 ")

(我确实理解防止重叠的一般目的,但我相信这里也存在GC竞争条件.)

编辑

命名空间是 System.Threading

Pra*_*eek 11

我认为这与GC没有关系,而是为了避免竞争条件:

赋值操作不是原子操作:首先创建Timer对象然后分配它.

所以这是一个场景:

  • new Timer(...) 创建计时器,它开始"计数"

  • 赋值结束之前,当前线程被抢占 => s_timer仍为空

  • 计时器唤醒另一个线程和调用Status,但最初的线程尚未完成赋值操作!

  • Status访问s_timer哪个是空引用 => BOOM!

使用他的方法不可能发生,例如使用相同的场景:

  • 计时器已创建但未启动

  • 当前线程被抢占

  • 没有任何反应,因为计时器尚未开始引发事件

  • 初始线程再次运行

  • 结束赋值 => s_timer 引用计时器

  • 计时器安全启动:任何将来的调用Status都是有效的,因为它s_timer是一个有效的引用