Does reactive extensions support rolling buffers?

后端 未结 4 655
时光说笑
时光说笑 2020-11-30 03:50

I\'m using reactive extensions to collate data into buffers of 100ms:

this.subscription = this.dataService
    .Where(x => !string.Equals(\"FOO\", x.Key.S         


        
4条回答
  •  一个人的身影
    2020-11-30 04:46

    I wrote an extension to do most of what you're after - BufferWithInactivity.

    Here it is:

    public static IObservable> BufferWithInactivity(
        this IObservable source,
        TimeSpan inactivity,
        int maximumBufferSize)
    {
        return Observable.Create>(o =>
        {
            var gate = new object();
            var buffer = new List();
            var mutable = new SerialDisposable();
            var subscription = (IDisposable)null;
            var scheduler = Scheduler.ThreadPool;
    
            Action dump = () =>
            {
                var bts = buffer.ToArray();
                buffer = new List();
                if (o != null)
                {
                    o.OnNext(bts);
                }
            };
    
            Action dispose = () =>
            {
                if (subscription != null)
                {
                    subscription.Dispose();
                }
                mutable.Dispose();
            };
    
            Action>>> onErrorOrCompleted =
                onAction =>
                {
                    lock (gate)
                    {
                        dispose();
                        dump();
                        if (o != null)
                        {
                            onAction(o);
                        }
                    }
                };
    
            Action onError = ex =>
                onErrorOrCompleted(x => x.OnError(ex));
    
            Action onCompleted = () => onErrorOrCompleted(x => x.OnCompleted());
    
            Action onNext = t =>
            {
                lock (gate)
                {
                    buffer.Add(t);
                    if (buffer.Count == maximumBufferSize)
                    {
                        dump();
                        mutable.Disposable = Disposable.Empty;
                    }
                    else
                    {
                        mutable.Disposable = scheduler.Schedule(inactivity, () =>
                        {
                            lock (gate)
                            {
                                dump();
                            }
                        });
                    }
                }
            };
    
            subscription =
                source
                    .ObserveOn(scheduler)
                    .Subscribe(onNext, onError, onCompleted);
    
            return () =>
            {
                lock (gate)
                {
                    o = null;
                    dispose();
                }
            };
        });
    }
    

提交回复
热议问题