<PackageReference Include="System.Reactive" Version="4.0.0-preview.2.build.379" />

Scheduler

public static class Scheduler
Provides a set of static properties to access commonly used schedulers.
using System.Globalization; using System.Reactive.Disposables; using System.Reactive.PlatformServices; using System.Threading; using System.Threading.Tasks; namespace System.Reactive.Concurrency { public static class Scheduler { private sealed class CancelableScheduler : IScheduler { private readonly IScheduler _scheduler; private readonly CancellationToken _cancellationToken; public CancellationToken Token => _cancellationToken; public DateTimeOffset Now => _scheduler.Now; public CancelableScheduler(IScheduler scheduler, CancellationToken cancellationToken) { _scheduler = scheduler; _cancellationToken = cancellationToken; } public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action) { return _scheduler.Schedule(state, action); } public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action) { return _scheduler.Schedule(state, dueTime, action); } public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action) { return _scheduler.Schedule(state, dueTime, action); } } [Serializable] private struct Pair<T1, T2> { public T1 First; public T2 Second; } private sealed class SchedulePeriodicStopwatch<TState> { private readonly IScheduler _scheduler; private readonly TimeSpan _period; private readonly Func<TState, TState> _action; private readonly IStopwatchProvider _stopwatchProvider; private TState _state; private readonly object _gate = new object(); private readonly AutoResetEvent _resumeEvent = new AutoResetEvent(false); private volatile int _runState; private IStopwatch _stopwatch; private TimeSpan _nextDue; private TimeSpan _suspendedAt; private TimeSpan _inactiveTime; private const int STOPPED = 0; private const int RUNNING = 1; private const int SUSPENDED = 2; private const int DISPOSED = 3; public SchedulePeriodicStopwatch(IScheduler scheduler, TState state, TimeSpan period, Func<TState, TState> action, IStopwatchProvider stopwatchProvider) { _scheduler = scheduler; _period = period; _action = action; _stopwatchProvider = stopwatchProvider; _state = state; _runState = 0; } public IDisposable Start() { RegisterHostLifecycleEventHandlers(); _stopwatch = _stopwatchProvider.StartStopwatch(); _nextDue = _period; _runState = 1; return StableCompositeDisposable.Create(_scheduler.Schedule(_nextDue, Tick), Disposable.Create(Cancel)); } private void Tick(Action<TimeSpan> recurse) { _nextDue += _period; _state = _action(_state); TimeSpan obj = default(TimeSpan); while (true) { bool flag = false; lock (_gate) { if (_runState != 1) { if (_runState == 3) return; flag = true; goto IL_0098; } obj = Normalize(_nextDue - (_stopwatch.Elapsed - _inactiveTime)); } break; IL_0098: if (flag) _resumeEvent.WaitOne(); } recurse(obj); } private void Cancel() { UnregisterHostLifecycleEventHandlers(); lock (_gate) { _runState = 3; if (!Environment.HasShutdownStarted) _resumeEvent.Set(); } } private void Suspending(object sender, HostSuspendingEventArgs args) { lock (_gate) { if (_runState == 1) { _suspendedAt = _stopwatch.Elapsed; _runState = 2; if (!Environment.HasShutdownStarted) _resumeEvent.Reset(); } } } private void Resuming(object sender, HostResumingEventArgs args) { lock (_gate) { if (_runState == 2) { _inactiveTime += _stopwatch.Elapsed - _suspendedAt; _runState = 1; if (!Environment.HasShutdownStarted) _resumeEvent.Set(); } } } private void RegisterHostLifecycleEventHandlers() { HostLifecycleService.Suspending += Suspending; HostLifecycleService.Resuming += Resuming; HostLifecycleService.AddRef(); } private void UnregisterHostLifecycleEventHandlers() { HostLifecycleService.Suspending -= Suspending; HostLifecycleService.Resuming -= Resuming; HostLifecycleService.Release(); } } private sealed class SchedulePeriodicRecursive<TState> { private readonly IScheduler _scheduler; private readonly TimeSpan _period; private readonly Func<TState, TState> _action; private TState _state; private int _pendingTickCount; private IDisposable _cancel; private const int TICK = 0; private const int DISPATCH_START = 1; private const int DISPATCH_END = 2; public SchedulePeriodicRecursive(IScheduler scheduler, TState state, TimeSpan period, Func<TState, TState> action) { _scheduler = scheduler; _period = period; _action = action; _state = state; } public IDisposable Start() { _pendingTickCount = 0; SingleAssignmentDisposable singleAssignmentDisposable = (SingleAssignmentDisposable)(_cancel = new SingleAssignmentDisposable()); singleAssignmentDisposable.Disposable = Scheduler.Schedule<int>(_scheduler, 0, _period, (Action<int, Action<int, TimeSpan>>)Tick); return singleAssignmentDisposable; } private void Tick(int command, Action<int, TimeSpan> recurse) { switch (command) { case 0: recurse(0, _period); if (Interlocked.Increment(ref _pendingTickCount) != 1) break; goto case 1; case 1: try { _state = _action(_state); } catch (Exception exception) { _cancel.Dispose(); exception.Throw(); } recurse(2, TimeSpan.Zero); break; case 2: if (Interlocked.Decrement(ref _pendingTickCount) > 0) recurse(1, TimeSpan.Zero); break; } } } private sealed class EmulatedStopwatch : IStopwatch { private readonly IScheduler _scheduler; private readonly DateTimeOffset _start; public TimeSpan Elapsed => Normalize(_scheduler.Now - _start); public EmulatedStopwatch(IScheduler scheduler) { _scheduler = scheduler; _start = _scheduler.Now; } } private static Lazy<IScheduler> s_threadPool = new Lazy<IScheduler>(() => Initialize("ThreadPool")); private static Lazy<IScheduler> s_newThread = new Lazy<IScheduler>(() => Initialize("NewThread")); private static Lazy<IScheduler> s_taskPool = new Lazy<IScheduler>(() => Initialize("TaskPool")); internal static Type[] OPTIMIZATIONS = new Type[3] { typeof(ISchedulerLongRunning), typeof(IStopwatchProvider), typeof(ISchedulerPeriodic) }; public static DateTimeOffset Now => SystemClock.UtcNow; public static ImmediateScheduler Immediate => ImmediateScheduler.Instance; public static CurrentThreadScheduler CurrentThread => CurrentThreadScheduler.Instance; public static DefaultScheduler Default => DefaultScheduler.Instance; [Obsolete("This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Consider using Scheduler.Default to obtain the platform's most appropriate pool-based scheduler. In order to access a specific pool-based scheduler, please add a reference to the System.Reactive.PlatformServices assembly for your target platform and use the appropriate scheduler in the System.Reactive.Concurrency namespace.")] public static IScheduler ThreadPool { get { return s_threadPool.Value; } } [Obsolete("This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Please use NewThreadScheduler.Default to obtain an instance of this scheduler type.")] public static IScheduler NewThread { get { return s_newThread.Value; } } [Obsolete("This property is no longer supported due to refactoring of the API surface and elimination of platform-specific dependencies. Please use TaskPoolScheduler.Default to obtain an instance of this scheduler type.")] public static IScheduler TaskPool { get { return s_taskPool.Value; } } public static SchedulerOperation Yield(this IScheduler scheduler) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new SchedulerOperation((Action a) => scheduler.Schedule(a), scheduler.GetCancellationToken()); } public static SchedulerOperation Yield(this IScheduler scheduler, CancellationToken cancellationToken) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new SchedulerOperation((Action a) => scheduler.Schedule(a), cancellationToken); } public static SchedulerOperation Sleep(this IScheduler scheduler, TimeSpan dueTime) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new SchedulerOperation((Action a) => scheduler.Schedule(dueTime, a), scheduler.GetCancellationToken()); } public static SchedulerOperation Sleep(this IScheduler scheduler, TimeSpan dueTime, CancellationToken cancellationToken) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new SchedulerOperation((Action a) => scheduler.Schedule(dueTime, a), cancellationToken); } public static SchedulerOperation Sleep(this IScheduler scheduler, DateTimeOffset dueTime) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new SchedulerOperation((Action a) => scheduler.Schedule(dueTime, a), scheduler.GetCancellationToken()); } public static SchedulerOperation Sleep(this IScheduler scheduler, DateTimeOffset dueTime, CancellationToken cancellationToken) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new SchedulerOperation((Action a) => scheduler.Schedule(dueTime, a), cancellationToken); } public static IDisposable ScheduleAsync<TState>(this IScheduler scheduler, TState state, Func<IScheduler, TState, CancellationToken, Task> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, state, action); } public static IDisposable ScheduleAsync<TState>(this IScheduler scheduler, TState state, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, state, action); } public static IDisposable ScheduleAsync(this IScheduler scheduler, Func<IScheduler, CancellationToken, Task> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, null, (IScheduler self, object o, CancellationToken ct) => action(self, ct)); } public static IDisposable ScheduleAsync(this IScheduler scheduler, Func<IScheduler, CancellationToken, Task<IDisposable>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, null, (IScheduler self, object o, CancellationToken ct) => action(self, ct)); } public static IDisposable ScheduleAsync<TState>(this IScheduler scheduler, TState state, TimeSpan dueTime, Func<IScheduler, TState, CancellationToken, Task> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, state, dueTime, action); } public static IDisposable ScheduleAsync<TState>(this IScheduler scheduler, TState state, TimeSpan dueTime, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, state, dueTime, action); } public static IDisposable ScheduleAsync(this IScheduler scheduler, TimeSpan dueTime, Func<IScheduler, CancellationToken, Task> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, null, dueTime, (IScheduler self, object o, CancellationToken ct) => action(self, ct)); } public static IDisposable ScheduleAsync(this IScheduler scheduler, TimeSpan dueTime, Func<IScheduler, CancellationToken, Task<IDisposable>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, null, dueTime, (IScheduler self, object o, CancellationToken ct) => action(self, ct)); } public static IDisposable ScheduleAsync<TState>(this IScheduler scheduler, TState state, DateTimeOffset dueTime, Func<IScheduler, TState, CancellationToken, Task> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, state, dueTime, action); } public static IDisposable ScheduleAsync<TState>(this IScheduler scheduler, TState state, DateTimeOffset dueTime, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, state, dueTime, action); } public static IDisposable ScheduleAsync(this IScheduler scheduler, DateTimeOffset dueTime, Func<IScheduler, CancellationToken, Task> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, null, dueTime, (IScheduler self, object o, CancellationToken ct) => action(self, ct)); } public static IDisposable ScheduleAsync(this IScheduler scheduler, DateTimeOffset dueTime, Func<IScheduler, CancellationToken, Task<IDisposable>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return ScheduleAsync_(scheduler, null, dueTime, (IScheduler self, object o, CancellationToken ct) => action(self, ct)); } private static IDisposable ScheduleAsync_<TState>(IScheduler scheduler, TState state, Func<IScheduler, TState, CancellationToken, Task> action) { return scheduler.Schedule(state, (IScheduler self, TState s) => Scheduler.InvokeAsync<TState>(self, s, action)); } private static IDisposable ScheduleAsync_<TState>(IScheduler scheduler, TState state, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { return scheduler.Schedule(state, (IScheduler self, TState s) => Scheduler.InvokeAsync<TState>(self, s, action)); } private static IDisposable ScheduleAsync_<TState>(IScheduler scheduler, TState state, TimeSpan dueTime, Func<IScheduler, TState, CancellationToken, Task> action) { return scheduler.Schedule(state, dueTime, (IScheduler self, TState s) => Scheduler.InvokeAsync<TState>(self, s, action)); } private static IDisposable ScheduleAsync_<TState>(IScheduler scheduler, TState state, TimeSpan dueTime, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { return scheduler.Schedule(state, dueTime, (IScheduler self, TState s) => Scheduler.InvokeAsync<TState>(self, s, action)); } private static IDisposable ScheduleAsync_<TState>(IScheduler scheduler, TState state, DateTimeOffset dueTime, Func<IScheduler, TState, CancellationToken, Task> action) { return scheduler.Schedule(state, dueTime, (IScheduler self, TState s) => Scheduler.InvokeAsync<TState>(self, s, action)); } private static IDisposable ScheduleAsync_<TState>(IScheduler scheduler, TState state, DateTimeOffset dueTime, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { return scheduler.Schedule(state, dueTime, (IScheduler self, TState s) => Scheduler.InvokeAsync<TState>(self, s, action)); } private static IDisposable InvokeAsync<TState>(IScheduler self, TState s, Func<IScheduler, TState, CancellationToken, Task<IDisposable>> action) { CancellationDisposable cancellationDisposable = new CancellationDisposable(); SingleAssignmentDisposable d = new SingleAssignmentDisposable(); action(new CancelableScheduler(self, cancellationDisposable.Token), s, cancellationDisposable.Token).ContinueWith((Action<Task<IDisposable>>)delegate(Task<IDisposable> t) { if (!t.IsCanceled) { if (t.Exception != null) t.Exception.Handle((Exception e) => e is OperationCanceledException); d.Disposable = t.Result; } }, TaskContinuationOptions.ExecuteSynchronously); return StableCompositeDisposable.Create(cancellationDisposable, d); } private static IDisposable InvokeAsync<TState>(IScheduler self, TState s, Func<IScheduler, TState, CancellationToken, Task> action) { return InvokeAsync(self, s, (IScheduler self_, TState state, CancellationToken ct) => action(self_, state, ct).ContinueWith<IDisposable>((Func<Task, IDisposable>)((Task _) => Disposable.Empty))); } private static CancellationToken GetCancellationToken(this IScheduler scheduler) { return (scheduler as CancelableScheduler)?.Token ?? CancellationToken.None; } public static TimeSpan Normalize(TimeSpan timeSpan) { if (timeSpan.Ticks >= 0) return timeSpan; return TimeSpan.Zero; } private static IScheduler Initialize(string name) { IScheduler service = PlatformEnlightenmentProvider.Current.GetService<IScheduler>(new object[1] { name }); if (service == null) throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings_Core.CANT_OBTAIN_SCHEDULER, name)); return service; } public static IDisposable Schedule(this IScheduler scheduler, Action<Action> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(action, delegate(Action<Action> _action, Action<Action<Action>> self) { _action(delegate { self(_action); }); }); } public static IDisposable Schedule<TState>(this IScheduler scheduler, TState state, Action<TState, Action<TState>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(new Pair<TState, Action<TState, Action<TState>>> { First = state, Second = action }, InvokeRec1); } private static IDisposable InvokeRec1<TState>(IScheduler scheduler, Pair<TState, Action<TState, Action<TState>>> pair) { CompositeDisposable group = new CompositeDisposable(1); object gate = new object(); TState first = pair.First; Action<TState, Action<TState>> action = (Action<TState, Action<TState>>)pair.Second; Action<TState> recursiveAction = null; recursiveAction = (Action<TState>)(Action<TState>)delegate(TState state1) { action(state1, delegate(TState state2) { bool isAdded = false; bool isDone = false; IDisposable d = null; d = scheduler.Schedule<TState>(state2, (Func<IScheduler, TState, IDisposable>)delegate(IScheduler scheduler1, TState state3) { lock (gate) { if (isAdded) group.Remove(d); else isDone = true; } recursiveAction(state3); return Disposable.Empty; }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); }; recursiveAction(first); return group; } public static IDisposable Schedule(this IScheduler scheduler, TimeSpan dueTime, Action<Action<TimeSpan>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(action, dueTime, delegate(Action<Action<TimeSpan>> _action, Action<Action<Action<TimeSpan>>, TimeSpan> self) { _action(delegate(TimeSpan dt) { self(_action, dt); }); }); } public static IDisposable Schedule<TState>(this IScheduler scheduler, TState state, TimeSpan dueTime, Action<TState, Action<TState, TimeSpan>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(new Pair<TState, Action<TState, Action<TState, TimeSpan>>> { First = state, Second = action }, dueTime, InvokeRec2); } private static IDisposable InvokeRec2<TState>(IScheduler scheduler, Pair<TState, Action<TState, Action<TState, TimeSpan>>> pair) { CompositeDisposable group = new CompositeDisposable(1); object gate = new object(); TState first = pair.First; Action<TState, Action<TState, TimeSpan>> action = (Action<TState, Action<TState, TimeSpan>>)pair.Second; Action<TState> recursiveAction = null; recursiveAction = (Action<TState>)(Action<TState>)delegate(TState state1) { action(state1, delegate(TState state2, TimeSpan dueTime1) { bool isAdded = false; bool isDone = false; IDisposable d = null; d = scheduler.Schedule<TState>(state2, dueTime1, (Func<IScheduler, TState, IDisposable>)delegate(IScheduler scheduler1, TState state3) { lock (gate) { if (isAdded) group.Remove(d); else isDone = true; } recursiveAction(state3); return Disposable.Empty; }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); }; recursiveAction(first); return group; } public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action<Action<DateTimeOffset>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(action, dueTime, delegate(Action<Action<DateTimeOffset>> _action, Action<Action<Action<DateTimeOffset>>, DateTimeOffset> self) { _action(delegate(DateTimeOffset dt) { self(_action, dt); }); }); } public static IDisposable Schedule<TState>(this IScheduler scheduler, TState state, DateTimeOffset dueTime, Action<TState, Action<TState, DateTimeOffset>> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(new Pair<TState, Action<TState, Action<TState, DateTimeOffset>>> { First = state, Second = action }, dueTime, InvokeRec3); } private static IDisposable InvokeRec3<TState>(IScheduler scheduler, Pair<TState, Action<TState, Action<TState, DateTimeOffset>>> pair) { CompositeDisposable group = new CompositeDisposable(1); object gate = new object(); TState first = pair.First; Action<TState, Action<TState, DateTimeOffset>> action = (Action<TState, Action<TState, DateTimeOffset>>)pair.Second; Action<TState> recursiveAction = null; recursiveAction = (Action<TState>)(Action<TState>)delegate(TState state1) { action(state1, delegate(TState state2, DateTimeOffset dueTime1) { bool isAdded = false; bool isDone = false; IDisposable d = null; d = scheduler.Schedule<TState>(state2, dueTime1, (Func<IScheduler, TState, IDisposable>)delegate(IScheduler scheduler1, TState state3) { lock (gate) { if (isAdded) group.Remove(d); else isDone = true; } recursiveAction(state3); return Disposable.Empty; }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); }; recursiveAction(first); return group; } public static ISchedulerLongRunning AsLongRunning(this IScheduler scheduler) { return As<ISchedulerLongRunning>(scheduler); } public static IStopwatchProvider AsStopwatchProvider(this IScheduler scheduler) { return As<IStopwatchProvider>(scheduler); } public static ISchedulerPeriodic AsPeriodic(this IScheduler scheduler) { return As<ISchedulerPeriodic>(scheduler); } private static T As<T>(IScheduler scheduler) where T : class { IServiceProvider serviceProvider; if ((serviceProvider = (scheduler as IServiceProvider)) != null) return (T)serviceProvider.GetService(typeof(T)); return null; } public static IDisposable SchedulePeriodic<TState>(this IScheduler scheduler, TState state, TimeSpan period, Func<TState, TState> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException("period"); if (action == null) throw new ArgumentNullException("action"); return SchedulePeriodic_(scheduler, state, period, action); } public static IDisposable SchedulePeriodic<TState>(this IScheduler scheduler, TState state, TimeSpan period, Action<TState> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException("period"); if (action == null) throw new ArgumentNullException("action"); return SchedulePeriodic_(scheduler, state, period, delegate(TState state_) { action(state_); return state_; }); } public static IDisposable SchedulePeriodic(this IScheduler scheduler, TimeSpan period, Action action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException("period"); if (action == null) throw new ArgumentNullException("action"); return SchedulePeriodic_(scheduler, action, period, delegate(Action a) { a(); return a; }); } public static IStopwatch StartStopwatch(this IScheduler scheduler) { if (scheduler == null) throw new ArgumentNullException("scheduler"); IStopwatchProvider stopwatchProvider = scheduler.AsStopwatchProvider(); if (stopwatchProvider != null) return stopwatchProvider.StartStopwatch(); return new EmulatedStopwatch(scheduler); } private static IDisposable SchedulePeriodic_<TState>(IScheduler scheduler, TState state, TimeSpan period, Func<TState, TState> action) { ISchedulerPeriodic schedulerPeriodic = scheduler.AsPeriodic(); if (schedulerPeriodic != null) return schedulerPeriodic.SchedulePeriodic(state, period, action); IStopwatchProvider stopwatchProvider = scheduler.AsStopwatchProvider(); if (stopwatchProvider != null) return new SchedulePeriodicStopwatch<TState>(scheduler, state, period, action, stopwatchProvider).Start(); return new SchedulePeriodicRecursive<TState>(scheduler, state, period, action).Start(); } public static IDisposable Schedule(this IScheduler scheduler, Action action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(action, Invoke); } public static IDisposable Schedule(this IScheduler scheduler, TimeSpan dueTime, Action action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(action, dueTime, Invoke); } public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.Schedule(action, dueTime, Invoke); } public static IDisposable ScheduleLongRunning(this ISchedulerLongRunning scheduler, Action<ICancelable> action) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (action == null) throw new ArgumentNullException("action"); return scheduler.ScheduleLongRunning(action, delegate(Action<ICancelable> a, ICancelable c) { a(c); }); } private static IDisposable Invoke(IScheduler scheduler, Action action) { action(); return Disposable.Empty; } public static IScheduler DisableOptimizations(this IScheduler scheduler) { if (scheduler == null) throw new ArgumentNullException("scheduler"); return new DisableOptimizationsScheduler(scheduler); } public static IScheduler DisableOptimizations(this IScheduler scheduler, params Type[] optimizationInterfaces) { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (optimizationInterfaces == null) throw new ArgumentNullException("optimizationInterfaces"); return new DisableOptimizationsScheduler(scheduler, optimizationInterfaces); } public static IScheduler Catch<TException>(this IScheduler scheduler, Func<TException, bool> handler) where TException : Exception { if (scheduler == null) throw new ArgumentNullException("scheduler"); if (handler == null) throw new ArgumentNullException("handler"); return new CatchScheduler<TException>(scheduler, handler); } } }