Get next event in sequence every second with reactive-extensions

前端 未结 3 1102
再見小時候
再見小時候 2021-01-20 16:08

I have the below types ...

public class NewsFeed
{
    public event EventHandler NewItem;

    .....

}

public class NewsItemEventA         


        
相关标签:
3条回答
  • 2021-01-20 16:34

    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);
    
    0 讨论(0)
  • 2021-01-20 16:35

    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);
    }
    
    0 讨论(0)
  • 2021-01-20 16:53

    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);
    
    0 讨论(0)
提交回复
热议问题