CatchScheduler<TException>
using System.Reactive.Disposables;
using System.Runtime.CompilerServices;
namespace System.Reactive.Concurrency
{
internal sealed class CatchScheduler<TException> : SchedulerWrapper where TException : Exception
{
private class CatchSchedulerLongRunning : ISchedulerLongRunning
{
private readonly ISchedulerLongRunning _scheduler;
private readonly Func<TException, bool> _handler;
public CatchSchedulerLongRunning(ISchedulerLongRunning scheduler, Func<TException, bool> handler)
{
_scheduler = scheduler;
_handler = handler;
}
public IDisposable ScheduleLongRunning<TState>(TState state, Action<TState, ICancelable> action)
{
return this._scheduler.ScheduleLongRunning<TState>(state, (Action<TState, ICancelable>)delegate(TState state_, ICancelable cancel) {
try {
action(state_, cancel);
} catch (TException val) when () {
}
});
}
}
private sealed class CatchSchedulerPeriodic : ISchedulerPeriodic
{
private readonly ISchedulerPeriodic _scheduler;
private readonly Func<TException, bool> _handler;
public CatchSchedulerPeriodic(ISchedulerPeriodic scheduler, Func<TException, bool> handler)
{
_scheduler = scheduler;
_handler = handler;
}
public IDisposable SchedulePeriodic<TState>(TState state, TimeSpan period, Func<TState, TState> action)
{
bool failed = false;
SingleAssignmentDisposable d = new SingleAssignmentDisposable();
d.Disposable = this._scheduler.SchedulePeriodic<TState>(state, period, (Func<TState, TState>)delegate(TState state_) {
if (!failed)
try {
return action(state_);
} catch (TException val) {
TException arg = (TException)val;
failed = true;
if (!this._handler(arg))
throw;
d.Dispose();
return default(TState);
}
return default(TState);
});
return d;
}
}
private readonly Func<TException, bool> _handler;
public CatchScheduler(IScheduler scheduler, Func<TException, bool> handler)
: base(scheduler)
{
_handler = handler;
}
protected override Func<IScheduler, TState, IDisposable> Wrap<TState>(Func<IScheduler, TState, IDisposable> action)
{
return delegate(IScheduler self, TState state) {
try {
return action(GetRecursiveWrapper(self), state);
} catch (TException val) when () {
return Disposable.Empty;
}
};
}
public CatchScheduler(IScheduler scheduler, Func<TException, bool> handler, ConditionalWeakTable<IScheduler, IScheduler> cache)
: base(scheduler, cache)
{
_handler = handler;
}
protected override SchedulerWrapper Clone(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache)
{
return new CatchScheduler<TException>(scheduler, _handler, cache);
}
protected override bool TryGetService(IServiceProvider provider, Type serviceType, out object service)
{
service = provider.GetService(serviceType);
if (service != null) {
if (serviceType == typeof(ISchedulerLongRunning))
service = new CatchSchedulerLongRunning((ISchedulerLongRunning)service, _handler);
else if (serviceType == typeof(ISchedulerPeriodic)) {
service = new CatchSchedulerPeriodic((ISchedulerPeriodic)service, _handler);
}
}
return true;
}
}
}