Skip to content

Commit 014d23a

Browse files
authored
ThreadPoolScheduler.Timer can be replaced by ordinarily scheduling a work item on a timer. (#633)
1 parent 8cdb5d0 commit 014d23a

File tree

1 file changed

+9
-71
lines changed

1 file changed

+9
-71
lines changed

Rx.NET/Source/src/System.Reactive/Concurrency/ThreadPoolScheduler.cs

Lines changed: 9 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,15 @@ public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Fun
6969
return Schedule(state, action);
7070
}
7171

72-
return new Timer<TState>(this, state, dt, action);
72+
var workItem = new UserWorkItem<TState>(this, state, action);
73+
74+
workItem.CancelQueueDisposable = new Timer(
75+
closureWorkItem => ((UserWorkItem<TState>)closureWorkItem).Run(),
76+
workItem,
77+
dt,
78+
Timeout.InfiniteTimeSpan);
79+
80+
return workItem;
7381
}
7482

7583
/// <summary>
@@ -161,76 +169,6 @@ public void Dispose()
161169
}
162170
}
163171

164-
//
165-
// See ConcurrencyAbstractionLayerImpl.cs for more information about the code
166-
// below and its timer rooting behavior.
167-
//
168-
169-
private sealed class Timer<TState> : IDisposable
170-
{
171-
private readonly MultipleAssignmentDisposable _disposable;
172-
173-
private readonly IScheduler _parent;
174-
private readonly TState _state;
175-
private Func<IScheduler, TState, IDisposable> _action;
176-
177-
private volatile System.Threading.Timer _timer;
178-
179-
public Timer(IScheduler parent, TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
180-
{
181-
_parent = parent;
182-
_state = state;
183-
_action = action;
184-
185-
_disposable = new MultipleAssignmentDisposable();
186-
_disposable.Disposable = Disposable.Create(Stop);
187-
188-
// Don't want the spin wait in Tick to get stuck if this thread gets aborted.
189-
try { }
190-
finally
191-
{
192-
//
193-
// Rooting of the timer happens through the passed state,
194-
// which is the current instance and has a field to store the Timer instance.
195-
//
196-
_timer = new System.Threading.Timer(_ => Tick(_) /* Don't convert to method group until Roslyn catches up */, this, dueTime, TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite));
197-
}
198-
}
199-
200-
private static void Tick(object state)
201-
{
202-
var timer = (Timer<TState>)state;
203-
204-
try
205-
{
206-
timer._disposable.Disposable = timer._action(timer._parent, timer._state);
207-
}
208-
finally
209-
{
210-
SpinWait.SpinUntil(timer.IsTimerAssigned);
211-
timer.Stop();
212-
}
213-
}
214-
215-
private bool IsTimerAssigned() => _timer != null;
216-
217-
public void Dispose() => _disposable.Dispose();
218-
219-
private void Stop()
220-
{
221-
var timer = _timer;
222-
if (timer != TimerStubs.Never)
223-
{
224-
_action = Nop;
225-
_timer = TimerStubs.Never;
226-
227-
timer.Dispose();
228-
}
229-
}
230-
231-
private IDisposable Nop(IScheduler scheduler, TState state) => Disposable.Empty;
232-
}
233-
234172
private sealed class PeriodicTimer<TState> : IDisposable
235173
{
236174
private TState _state;

0 commit comments

Comments
 (0)