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);
}
}
}