I have the below types ...
public class NewsFeed
{
public event EventHandler NewItem;
.....
}
public class NewsItemEventA
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);
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);
}
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);