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; })); }
public static IObservable <IList <T> > Buffer <T>(this IObservable <T> source, TimeSpan timeSpan, int count, IScheduler scheduler) { if (source == null) { throw new ArgumentNullException("source"); } if (count <= 0) { throw new ArgumentOutOfRangeException("count <= 0"); } return(Observable.Create <IList <T> >(observer => { var list = new List <T>(); var gate = new object(); var timerId = 0L; var d = new CompositeDisposable(2); var timerD = new SerialDisposable(); // timer d.Add(timerD); Action createTimer = () => { var currentTimerId = timerId; var timerS = new SingleAssignmentDisposable(); timerD.Disposable = timerS; // restart timer(dispose before) timerS.Disposable = scheduler.Schedule(timeSpan, self => { List <T> currentList; lock (gate) { if (currentTimerId != timerId) { return; } currentList = list; if (currentList.Count != 0) { list = new List <T>(); } } if (currentList.Count != 0) { observer.OnNext(currentList); } self(timeSpan); }); }; createTimer(); // subscription d.Add(source.Subscribe(x => { List <T> currentList = null; lock (gate) { list.Add(x); if (list.Count == count) { currentList = list; list = new List <T>(); timerId++; createTimer(); } } if (currentList != null) { observer.OnNext(currentList); } }, observer.OnError, () => { lock (gate) { timerId++; } var currentList = list; observer.OnNext(currentList); observer.OnCompleted(); })); return d; })); }
public static IObservable <IList <TSource> > Buffer <TSource, TWindowBoundary>(this IObservable <TSource> source, IObservable <TWindowBoundary> windowBoundaries) { return(Observable.Create <IList <TSource> >(observer => { var list = new List <TSource>(); var gate = new object(); var d = new CompositeDisposable(2); d.Add(source.Subscribe(Observer.Create <TSource>( x => { lock (gate) { list.Add(x); } }, ex => { lock (gate) { observer.OnError(ex); } }, () => { lock (gate) { var currentList = list; list = new List <TSource>(); // safe observer.OnNext(currentList); observer.OnCompleted(); } } ))); d.Add(windowBoundaries.Subscribe(Observer.Create <TWindowBoundary>( w => { List <TSource> currentList; lock (gate) { currentList = list; if (currentList.Count != 0) { list = new List <TSource>(); } } if (currentList.Count != 0) { observer.OnNext(currentList); } }, ex => { lock (gate) { observer.OnError(ex); } }, () => { lock (gate) { var currentList = list; list = new List <TSource>(); // safe observer.OnNext(currentList); observer.OnCompleted(); } } ))); return d; })); }
public void Dispose() { disposables.Dispose(); disposables = null; }