public static IObservable <T> Merge <T>(this IObservable <IObservable <T> > sources) { // this code is borrwed from RxOfficial(rx.codeplex.com) return(Observable.Create <T>(observer => { var gate = new object(); var isStopped = false; var m = new SingleAssignmentDisposable(); var group = new CompositeDisposable() { m }; m.Disposable = sources.Subscribe( innerSource => { var innerSubscription = new SingleAssignmentDisposable(); group.Add(innerSubscription); innerSubscription.Disposable = innerSource.Subscribe( x => { lock (gate) observer.OnNext(x); }, exception => { lock (gate) observer.OnError(exception); }, () => { group.Remove(innerSubscription); // modification MUST occur before subsequent check if (isStopped && group.Count == 1) // isStopped must be checked before group Count to ensure outer is not creating more groups { lock (gate) observer.OnCompleted(); } }); }, exception => { lock (gate) observer.OnError(exception); }, () => { isStopped = true; // modification MUST occur before subsequent check if (group.Count == 1) { lock (gate) observer.OnCompleted(); } }); return group; })); }
static IDisposable InvokeRec3 <TState>(IScheduler scheduler, Pair <TState, Action <TState, Action <TState, DateTimeOffset> > > pair) { var group = new CompositeDisposable(1); var gate = new object(); var state = pair.First; var action = pair.Second; Action <TState> recursiveAction = null; recursiveAction = state1 => action(state1, (state2, dueTime1) => { var isAdded = false; var isDone = false; var d = default(IDisposable); d = scheduler.Schedule(state2, dueTime1, (scheduler1, 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(state); return(group); }
public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action <Action <DateTimeOffset> > action) { // InvokeRec3 var group = new CompositeDisposable(1); var gate = new object(); Action recursiveAction = null; recursiveAction = () => action(dt => { var isAdded = false; var isDone = false; var d = default(IDisposable); d = scheduler.Schedule(dt, () => { lock (gate) { if (isAdded) { group.Remove(d); } else { isDone = true; } } recursiveAction(); }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); group.Add(scheduler.Schedule(dueTime, recursiveAction)); return(group); }
public static IDisposable Schedule(this IScheduler scheduler, TimeSpan dueTime, Action <Action <TimeSpan> > action) { CompositeDisposable group = new CompositeDisposable(1); object gate = new object(); Action recursiveAction = null; recursiveAction = delegate() { action(delegate(TimeSpan dt) { bool isAdded = false; bool isDone = false; IDisposable d = null; object gate; d = scheduler.Schedule(dt, delegate() { object gate2 = gate; lock (gate2) { if (isAdded) { group.Remove(d); } else { isDone = true; } } recursiveAction(); }); gate = gate; lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); }; group.Add(scheduler.Schedule(dueTime, recursiveAction)); return(group); }
public static IDisposable Schedule(this IScheduler scheduler, Action <Action> action) { // InvokeRec1 CompositeDisposable group = new CompositeDisposable(1); object gate = new object(); Action recursiveAction = null; recursiveAction = () => action(() => { bool isAdded = false; bool isDone = false; IDisposable d = default(IDisposable); d = scheduler.Schedule(() => { lock (gate) { if (isAdded) { group.Remove(d); } else { isDone = true; } } recursiveAction(); }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); group.Add(scheduler.Schedule(recursiveAction)); return(group); }
public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action <Action <DateTimeOffset> > action) { CompositeDisposable group = new CompositeDisposable(1); object gate = new object(); Action recursiveAction = null; recursiveAction = delegate { action(delegate(DateTimeOffset dt) { bool isAdded = false; bool isDone = false; IDisposable d = null; d = scheduler.Schedule(dt, (Action) delegate { lock (gate) { if (isAdded) { group.Remove(d); } else { isDone = true; } } recursiveAction(); }); lock (gate) { if (!isDone) { group.Add(d); isAdded = true; } } }); }; group.Add(scheduler.Schedule(dueTime, recursiveAction)); return(group); }
public static IObservable <T> Merge <T> (this IObservable <IObservable <T> > sources, int maxConcurrent) { // this code is borrwed from RxOfficial(rx.codeplex.com) return(Observable.Create <T> (observer => { var gate = new object(); var q = new Queue <IObservable <T> > (); var isStopped = false; var group = new CompositeDisposable(); var activeCount = 0; var subscribe = default(Action <IObservable <T> >); subscribe = xs => { var subscription = new SingleAssignmentDisposable(); group.Add(subscription); subscription.Disposable = xs.Subscribe( x => { lock (gate) observer.OnNext(x); }, exception => { lock (gate) observer.OnError(exception); }, () => { group.Remove(subscription); lock (gate) { if (q.Count > 0) { var s = q.Dequeue(); subscribe(s); } else { activeCount--; if (isStopped && activeCount == 0) { observer.OnCompleted(); } } } }); }; group.Add(sources.Subscribe( innerSource => { lock (gate) { if (activeCount < maxConcurrent) { activeCount++; subscribe(innerSource); } else { q.Enqueue(innerSource); } } }, exception => { lock (gate) observer.OnError(exception); }, () => { lock (gate) { isStopped = true; if (activeCount == 0) { observer.OnCompleted(); } } })); return group; })); }