Get next event in sequence every second with reactive-extensions

血红的双手。 提交于 2019-12-20 02:15:24

问题


I have the below types ...

public class NewsFeed
{
    public event EventHandler<NewsItemEventArgs> NewItem;

    .....

}

public class NewsItemEventArgs : EventArgs
{
    public NewsItem Item;
    public NewsItemEventArgs(NewsItem newsItem)
    {
        Item = newsItem;
    }
}

public class NewsItem
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

The NewsFeed's NewItem event fires events with eventArgs of type NewsItemEventArgs. In my system the events are published in bursts, say 10 NewsItems in a small 1 second window and then no further news stories for 60 seconds. I would like to smooth these bursts out with RX so my in my UI news stories 'appear' to arrive one at a time in more regular intervals of say 5 seconds.

I know I need to create an observable with something like the below

_source = Observable.FromEventPattern<NewsItemEventArgs>(
                        h => _newsFeed.NewItem += h,
                        h => _newsFeed.NewItem -= h);

but I dont know how to transform and subscribe to the observable such that I get drip fed the events rather than them coming in the bursts described above.

Any ideas?


回答1:


You could zip your sequence with another which produces values at regular intervals:

Observable<NewsItem> nis = _source
    .Zip(Observable.Timer(Timespan.FromSeconds(5), TimeSpan.FromSeconds(5)), (e, _) => e)
    .Select(eventArgs => eventArgs.Item);



回答2:


Zip might not be the best choice for this operation because there's a chance for the producer to be slow at times, resulting a jittery output.

It seems accurate scheduling with DateTimeOffset still isn't possible with Rx 2.0. TimeSpan works for now, though. You can try it by replacing the TimeSpan offset with a DateTimeOffset.

In summary, if we can specify a minimum interval between two consecutive values, we can solve the burst problem.

    static IObservable<T> DelayBetweenValues<T>(this IObservable<T> observable, TimeSpan interval, IScheduler scheduler)
    {
        return Observable.Create<T>(observer =>
        {
            var offset = TimeSpan.Zero;
            return observable
                .TimeInterval(scheduler)
                .Subscribe
                (
                    ts =>
                    {
                        if (ts.Interval < interval)
                        {
                            offset = offset.Add(interval);
                            scheduler.Schedule(offset, () => observer.OnNext(ts.Value));
                        }
                        else
                        {
                            offset = TimeSpan.Zero;
                            observer.OnNext(ts.Value);
                        }
                    }
                );
        });
    }

Test:

        Observable.Interval(TimeSpan.FromSeconds(2.5))
                  .Do(_ => Console.WriteLine("Burst"))
                  .SelectMany(i => Enumerable.Range((int)i, 10))
                  .DelayBetweenValues(TimeSpan.FromSeconds(0.2), TaskPoolScheduler.Default)
                  .Subscribe(Console.WriteLine);



回答3:


I couldn't get the answer from Asti to work. So I tried the undocumented Delay overload with the delayDurationSelector. I got it working for my problem, though somehow it's not behaving correctly when I use the scheduler in the timer, but it works without it:

public static IObservable<T> DelayBetweenValues<T>(this IObservable<T> observable, TimeSpan interval,
    IScheduler scheduler)
{
        var offset =  TimeSpan.Zero;
        return observable
            .TimeInterval(scheduler)
            .Delay(ti =>
            {
                offset = (ti.Interval < interval) ? offset.Add(interval) : TimeSpan.Zero;
                return Observable.Timer(offset);
            })
            .Select(ti => ti.Value);
}


来源:https://stackoverflow.com/questions/12651806/get-next-event-in-sequence-every-second-with-reactive-extensions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!