DispatcherScheduler
using System.Reactive.Disposables;
using System.Threading;
using System.Windows.Threading;
namespace System.Reactive.Concurrency
{
public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic
{
[Obsolete("Use the Current property to retrieve the DispatcherScheduler instance for the current thread's Dispatcher object.")]
public static DispatcherScheduler Instance {
get {
return new DispatcherScheduler(Dispatcher.get_CurrentDispatcher());
}
}
public static DispatcherScheduler Current {
get {
Dispatcher val = Dispatcher.FromThread(Thread.CurrentThread);
if ((int)val == 0)
throw new InvalidOperationException(Strings_WindowsThreading.NO_DISPATCHER_CURRENT_THREAD);
return new DispatcherScheduler(val);
}
}
public Dispatcher Dispatcher { get; }
public DispatcherPriority Priority { get; }
public DispatcherScheduler(Dispatcher dispatcher)
{
if (dispatcher == null)
throw new ArgumentNullException("dispatcher");
Dispatcher = dispatcher;
Priority = 9;
}
public DispatcherScheduler(Dispatcher dispatcher, DispatcherPriority priority)
{
if (dispatcher == null)
throw new ArgumentNullException("dispatcher");
Dispatcher = dispatcher;
Priority = priority;
}
public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
throw new ArgumentNullException("action");
SingleAssignmentDisposable d = new SingleAssignmentDisposable();
Dispatcher.BeginInvoke((Delegate)(Action)delegate {
if (!d.IsDisposed)
d.Disposable = action(this, state);
}, Priority, Array.Empty<object>());
return d;
}
public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
throw new ArgumentNullException("action");
TimeSpan dueTime2 = Scheduler.Normalize(dueTime);
if (dueTime2.Ticks == 0)
return Schedule(state, action);
return ScheduleSlow(state, dueTime2, action);
}
private IDisposable ScheduleSlow<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
MultipleAssignmentDisposable d = new MultipleAssignmentDisposable();
DispatcherTimer timer = new DispatcherTimer(Priority, Dispatcher);
timer.add_Tick((EventHandler)delegate {
DispatcherTimer val2 = Interlocked.Exchange<DispatcherTimer>(ref timer, null);
if (val2 != null)
try {
d.Disposable = action(this, state);
} finally {
val2.Stop();
action = null;
}
});
timer.set_Interval(dueTime);
timer.Start();
d.Disposable = Disposable.Create(delegate {
DispatcherTimer val = Interlocked.Exchange<DispatcherTimer>(ref timer, null);
if (val != null) {
val.Stop();
action = ((IScheduler _, TState __) => Disposable.Empty);
}
});
return d;
}
public IDisposable SchedulePeriodic<TState>(TState state, TimeSpan period, Func<TState, TState> action)
{
if (period < TimeSpan.Zero)
throw new ArgumentOutOfRangeException("period");
if (action == null)
throw new ArgumentNullException("action");
DispatcherTimer timer = new DispatcherTimer(Priority, Dispatcher);
timer.add_Tick((EventHandler)delegate {
state = action(state);
});
timer.set_Interval(period);
timer.Start();
return Disposable.Create(delegate {
DispatcherTimer val = Interlocked.Exchange<DispatcherTimer>(ref timer, null);
if (val != null) {
val.Stop();
action = ((TState _) => _);
}
});
}
}
}