/// <summary> /// Queue a call to complete the wait on the ThreadPool. /// </summary> /// <param name="registeredHandle">The handle that completed.</param> /// <param name="timedOut">Whether or not the wait timed out.</param> private void QueueWaitCompletion(RegisteredWaitHandle registeredHandle, bool timedOut) { registeredHandle.RequestCallback(); // If the handle is a repeating handle, set up the next call. Otherwise, remove it from the wait thread. if (registeredHandle.Repeating) { registeredHandle.RestartTimeout(); } else { UnregisterWait(registeredHandle, blocking: false); // We shouldn't block the wait thread on the unregistration. } ThreadPool.UnsafeQueueHighPriorityWorkItemInternal( new CompleteWaitThreadPoolWorkItem(registeredHandle, timedOut)); }
/// <summary> /// This method is executed on a dedicated a timer thread. Its purpose is /// to handle timer requests and notify the TimerQueue when a timer expires. /// </summary> private static void TimerThread() { AutoResetEvent timerEvent = s_timerEvent; List <TimerQueue> timersToFire = s_scheduledTimersToFire !; List <TimerQueue> timers; lock (timerEvent) { timers = s_scheduledTimers !; } int shortestWaitDurationMs = Timeout.Infinite; while (true) { timerEvent.WaitOne(shortestWaitDurationMs); long currentTimeMs = TickCount64; shortestWaitDurationMs = int.MaxValue; lock (timerEvent) { for (int i = timers.Count - 1; i >= 0; --i) { TimerQueue timer = timers[i]; long waitDurationMs = timer._scheduledDueTimeMs - currentTimeMs; if (waitDurationMs <= 0) { timer._isScheduled = false; timersToFire.Add(timer); int lastIndex = timers.Count - 1; if (i != lastIndex) { timers[i] = timers[lastIndex]; } timers.RemoveAt(lastIndex); continue; } if (waitDurationMs < shortestWaitDurationMs) { shortestWaitDurationMs = (int)waitDurationMs; } } } if (timersToFire.Count > 0) { foreach (TimerQueue timerToFire in timersToFire) { ThreadPool.UnsafeQueueHighPriorityWorkItemInternal(timerToFire); } timersToFire.Clear(); } if (shortestWaitDurationMs == int.MaxValue) { shortestWaitDurationMs = Timeout.Infinite; } } }