Let\'s pretend I have something like this:
And something like this:
publ
I have a couple of combinators called SubscribeWithoutOverlap I use in the UI for this purpose. All incoming events are discarded except the last one are discarded till the work is finished. When the work is finished the event buffer is asked for the next event.
///
/// Subscribe to the observable whilst discarding all events that are
/// recieved whilst the action is being processed. Can be
/// used to improve resposiveness of UI's for example
///
///
///
///
///
///
public static IDisposable SubscribeWithoutOverlap
(this IObservable source, Action action, IScheduler scheduler = null)
{
var sampler = new Subject();
scheduler = scheduler ?? Scheduler.Default;
var p = source.Replay(1);
var subscription = sampler.Select(x=>p.Take(1))
.Switch()
.ObserveOn(scheduler)
.Subscribe(l =>
{
action(l);
sampler.OnNext(Unit.Default);
});
var connection = p.Connect();
sampler.OnNext(Unit.Default);
return new CompositeDisposable(connection, subscription);
}
and
public static IDisposable SubscribeWithoutOverlap
(this IObservable source, Func action, IScheduler scheduler = null)
{
var sampler = new Subject();
scheduler = scheduler ?? Scheduler.Default;
var p = source.Replay(1);
var subscription = sampler.Select(x=>p.Take(1))
.Switch()
.ObserveOn(scheduler)
.Subscribe(async l =>
{
await action(l);
sampler.OnNext(Unit.Default);
});
var connection = p.Connect();
sampler.OnNext(Unit.Default);
return new CompositeDisposable(connection, subscription);
}
so the following should then meet your requirements.
IObservable source;
source
.Throttle(TimeSpan.FromMilliSeconds(100))
.Merge(source.Sample(TimeSpan.FromSeconds(1))
.SubscribeWithoutOverlap(DoWork)
Note the mix of Throttle and Sample to get both timing behaviors asked for in the question.
With regards to some of the other answers. If you find yourself putting complex RX logic into your business logic then extract into a custom combinator that has a clear purpose. You will thank yourself later when trying to understand what it does.