Queue TimerQueueTimer directly to ThreadPool
authorStephen Toub <stoub@microsoft.com>
Mon, 16 Oct 2017 19:09:52 +0000 (15:09 -0400)
committerStephen Toub <stoub@microsoft.com>
Mon, 16 Oct 2017 19:09:52 +0000 (15:09 -0400)
Eliminate a wrapper ThreadPoolWorkItem that's unnecessary.  Saves an allocation ever time a Timer fires.

src/mscorlib/src/System/Threading/Timer.cs

index d46bf6b..11b46ab 100644 (file)
@@ -345,20 +345,8 @@ namespace System.Threading
 
         private static void QueueTimerCompletion(TimerQueueTimer timer)
         {
-            WaitCallback callback = s_fireQueuedTimerCompletion;
-            if (callback == null)
-                s_fireQueuedTimerCompletion = callback = new WaitCallback(FireQueuedTimerCompletion);
-
-            // Can use "unsafe" variant because we take care of capturing and restoring
-            // the ExecutionContext.
-            ThreadPool.UnsafeQueueUserWorkItem(callback, timer);
-        }
-
-        private static WaitCallback s_fireQueuedTimerCompletion;
-
-        private static void FireQueuedTimerCompletion(object state)
-        {
-            ((TimerQueueTimer)state).Fire();
+            // Can use "unsafe" variant because we take care of capturing and restoring the ExecutionContext.
+            ThreadPool.UnsafeQueueCustomWorkItem(timer, forceGlobal: true);
         }
 
         #endregion
@@ -407,7 +395,7 @@ namespace System.Threading
     //
     // A timer in our TimerQueue.
     //
-    internal sealed class TimerQueueTimer
+    internal sealed class TimerQueueTimer : IThreadPoolWorkItem
     {
         //
         // The associated timer queue.
@@ -600,6 +588,10 @@ namespace System.Threading
                 SignalNoCallbacksRunning();
         }
 
+        void IThreadPoolWorkItem.ExecuteWorkItem() => Fire();
+
+        void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { }
+
         internal void SignalNoCallbacksRunning()
         {
             Win32Native.SetEvent(m_notifyWhenNoCallbacksRunning.SafeWaitHandle);