瀏覽代碼

ThreadPoolScheduler.Timer can be replaced by ordinarily scheduling a work item on a timer. (#633)

Daniel C. Weber 7 年之前
父節點
當前提交
014d23a400
共有 1 個文件被更改,包括 9 次插入71 次删除
  1. 9 71
      Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.cs

+ 9 - 71
Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.cs

@@ -69,7 +69,15 @@ namespace System.Reactive.Concurrency
                 return Schedule(state, action);
             }
 
-            return new Timer<TState>(this, state, dt, action);
+            var workItem = new UserWorkItem<TState>(this, state, action);
+
+            workItem.CancelQueueDisposable = new Timer(
+                closureWorkItem => ((UserWorkItem<TState>)closureWorkItem).Run(),
+                workItem,
+                dt,
+                Timeout.InfiniteTimeSpan);
+
+            return workItem;
         }
 
         /// <summary>
@@ -161,76 +169,6 @@ namespace System.Reactive.Concurrency
             }
         }
 
-        //
-        // See ConcurrencyAbstractionLayerImpl.cs for more information about the code
-        // below and its timer rooting behavior.
-        //
-
-        private sealed class Timer<TState> : IDisposable
-        {
-            private readonly MultipleAssignmentDisposable _disposable;
-
-            private readonly IScheduler _parent;
-            private readonly TState _state;
-            private Func<IScheduler, TState, IDisposable> _action;
-
-            private volatile System.Threading.Timer _timer;
-
-            public Timer(IScheduler parent, TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
-            {
-                _parent = parent;
-                _state = state;
-                _action = action;
-
-                _disposable = new MultipleAssignmentDisposable();
-                _disposable.Disposable = Disposable.Create(Stop);
-
-                // Don't want the spin wait in Tick to get stuck if this thread gets aborted.
-                try { }
-                finally
-                {
-                    //
-                    // Rooting of the timer happens through the passed state,
-                    // which is the current instance and has a field to store the Timer instance.
-                    //
-                    _timer = new System.Threading.Timer(_ => Tick(_) /* Don't convert to method group until Roslyn catches up */, this, dueTime, TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite));
-                }
-            }
-
-            private static void Tick(object state)
-            {
-                var timer = (Timer<TState>)state;
-
-                try
-                {
-                    timer._disposable.Disposable = timer._action(timer._parent, timer._state);
-                }
-                finally
-                {
-                    SpinWait.SpinUntil(timer.IsTimerAssigned);
-                    timer.Stop();
-                }
-            }
-
-            private bool IsTimerAssigned() => _timer != null;
-
-            public void Dispose() => _disposable.Dispose();
-
-            private void Stop()
-            {
-                var timer = _timer;
-                if (timer != TimerStubs.Never)
-                {
-                    _action = Nop;
-                    _timer = TimerStubs.Never;
-
-                    timer.Dispose();
-                }
-            }
-
-            private IDisposable Nop(IScheduler scheduler, TState state) => Disposable.Empty;
-        }
-
         private sealed class PeriodicTimer<TState> : IDisposable
         {
             private TState _state;