I'm trying to implement the following scenario:
interval
is calculated by calling the GetInterval()
method.DoSomething()
method is called immediately.DoSomething()
method will be called repeatedly every interval
milliseconds until the button is released.It could be implemented as follows:
Timer timer = new Timer();
timer.Tick += DoSomething();
//keyDown and keyUp are IObservables created from the button's events
keyDown.Do(_ =>
{
timer.Interval = GetInterval();
timer.Start();
DoSomething();
});
keyUp.Do(_ =>
{
timer.Stop();
});
I know this code have some problems, but it does not matter. What I'm trying to achieve is to implement this scenario using pure Reactive Extensions, without any external timers and side effects (other than calling the DoSomething()
method).
I know of Observable.Timer, but I do not know how to use it in this scenario.
EDIT: I can create an IObservable<int>
containing current values of the interval
. It will probably help.
I'm going to suggest that an approach using Select
/Switch
is going to be better than an approach using SelectMany
.
In general, when using SelectMany
you may end up with a memory leak as more and more underlying subscriptions are created. This may not happen in this case due to the TakeUntil
, but it is worth getting into the habit of avoiding this.
Here's my code:
var subscription =
keyDown
.Select(kd =>
Observable
.Interval(TimeSpan.FromMilliseconds(500))
.TakeUntil(keyUp)
.StartWith(-1L))
.Switch()
.Subscribe(n => DoSomething());
When using the Switch
you must construct an IObservable<IObservable<T>>
to call .Switch()
on which takes the latest IObservable<T>
produced by the IObservable<IObservable<T>>
and flattens it similar to a SelectMany
but the former disposes of the previous observable and the latter doesn't.
I've also included a StartWith
that ensures that the sequence immediately produces a value.
keyDown
.SelectMany(_ =>
Observable.Interval(TimeSpan.FromMilliseconds(500))
.TakeUntil(keyUp))
.Subscribe(_ => DoSomething());
This will start an interval on every keydown event. The timer will complete on a keyup event being emited.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With