private WaitHandle notifyObject; // Who do notify when object disposed // // Private constructor - used to ensure all constructors initialise // the object in the same way. // private Timer(TimerCallback callback, Object state) { // // Validate the parameters. // if (callback == null) { throw new ArgumentNullException("callback"); } // // If this is the first timer constructed allocate resources // for the timer thread and start it. // lock (typeof(Timer)) { if (Timer.alarmClock == null) { if (!Thread.CanStartThreads()) { throw new NotImplementedException(); } Timer.alarmClock = new AlarmClock(); Timer.disposeQueue = new System.Collections.Queue(); Timer.now = Timer.UtcMilliseconds(); Timer.threadWakeup = new AutoResetEvent(false); Timer.timerThread = new Thread(new ThreadStart(Timer.Run)); Timer.timerThread.IsBackground = true; Timer.timerThread.Start(); } } // // Initialize the timer state. // lock (this) { this.disposed = false; this.alarm = Timer.alarmClock.CreateAlarm( new AlarmClock.AlarmExpiredHandler(this.fireTimer)); this.callback = callback; this.state = state; } }
// // Advance the time in the Alarm object so it is the same as the // real time. // private static void AdvanceTime(long timerPeriod) { long elapsed; lock (typeof(Timer)) { long was = Timer.now; Timer.now = Timer.UtcMilliseconds(); elapsed = Timer.now - was; } // if elapsed is less then zero the system time might have been changed to the past. // so dont sleep. This works well. if (elapsed < 0) { elapsed = 0; } // if elapsed is greater then x*timerPeriod the system time might have been changed to the future. // This is a workaround. but works. else if (timerPeriod > 0 && elapsed > 10 * timerPeriod) { elapsed = 0; } Timer.alarmClock.Sleep(elapsed); }