Solution #2 - Implementing the DelayTextBox using the IObservable interface from ReactiveExtensions
After seeing Part 1, now I will implement a DelayTextBox class (we’ll call it DelayTextBoxReactive) using the IObservable.Throttle method from the Reactive Extensions framework.
This method ignores values from an observable sequence that are followed by another value before the specified time span.
public DelayTextBoxReactive()
public IDisposable Subscribe(Action<string> handler, double delay)
var textChanged = Observable.FromEvent<EventArgs>(this, "TextChanged");
textChanged.Throttle(TimeSpan.FromMilliseconds(delay)).ObserveOn(this).
Subscribe(args => handler(this.Text));
return textChanged as IDisposable;
Note: The delay variable represents the time to wait for the user’s input (similar to the Delay property in the first approach).
I’m detailing below each part of this code:
var textChanged = Observable.FromEvent< EventArgs >(this, "TextChanged");
Basically, this code creates an IObservable object for the TextChanged event of the TextBox.
textChanged.Throttle(TimeSpan.FromMilliseconds(delay));
This specifies that the IObservable must ignore TextChanged events raised before the specified time has elapsed.
ObserveOn(this).Subscribe(args = > handler(this.Text));
After the time has elapsed without any TextChanged event being raised, this code asynchronously notifies the observers by calling the handler (in our case, this is a void method with a string parameter).
At this point, you can use the DelayTextBoxReactive class in your form / user control as follows:
textBoxInput.Subscribe(OnTextChangeCompleted, Constants.DefaultDelayDelta);
Note: in this example, textBoxInput is of type DelayTextBoxReactive.
Conclusion:
As compared to solution #1 (using a Timer), the second approach (using the Rx / Reactive Extensions library) brings quite a few advantages:
- A major advantage is the fact that memory leaks can be easily prevented, as Rx provides a more intuitive mechanism for event handling disposal (the Subscribe method returns an IDisposable reference).
- Reactive Extensions simplifies a lot of aspects of asynchronous programming, as it reduces the necessary effort for implementing a solution (for example, in my samples above, the code for the DelayTextBox implementation is significantly larger than the DelayTextBoxReactive implementation).
- Increased code clarity and LINQ fluent method call syntax.