As written before the Reactive Extensions for .NET (Rx, aka „Reactive Framework“) have been published as pre-release on their own DevLabs-site. The Rx-team is asking for feedback from you as developers and will include improvements into timely released development packages, until they’ll ship the final pieces with .NET 4.0. Check out the MSDN forum to give your feedback or ask for support.
So what’s new in Rx compared to the early DLL from the Silverlight 3 toolkit sources?
In general, many improvements were made on the API and functionality: methods on the Observable
class have been rearranged and extended to give you full flexibility in many use cases. One method that I really love is Throttle()
. Imagine that you have a textbox and everytime the user makes an input (without pressing Return) a data source is queried for items that match this input in some way (e.g. filtering by name or something). Now you discover that you’ve got performance issues. The search is done as the user types the first character and that’s not what you want. You only want to react to user’s input if he isn’t typing anything for -let’s say- 1 second. Throttle()
solves this for you by one method call, you do not need anything else or do something manually. That’s great! Try to develop this with common event-based programming and you know what I mean…
Then the Rx-team intends to converge the functionality of IEnumerable and IObservable. IObservable has much of the functionality of IEnumerable and LINQ operators make composing, filtering and transformation of event streams very simple and intuitive. And in the DevLabs-release of Rx the Rx-team is moving some functionality from IObservable (such as the Amb()
method) to IEnumerable as well. If you need it or not: this is leveraging the dualism of both concepts for developers and makes both interfaces more intuitively usable.
Furthermore the ground base of Rx is now Px (or PFx), the Parallel Extensions for .NET that will be part of .NET 4.0 as well. For every concurrent operation Px is taken and does the whole work (by creating a Task<T>
). As a side effect of supporting Rx for .NET 3.5 SP1, the Rx-team has back-ported Px from .NET 4.0 to .NET 3.5 SP1 and made it usable for this platform as well. Great job!
One thing very cool and worth to mention are Subjects as new components in Rx. Subjects implement the type ISubject<S,T>
and are kind of hybrids between IObserver<S>
and IObservable<T>
. A Subject implements both IObservable
and IObserver
and can be seen as „channel“ or „transforming storage“. The channel behavior is that you can push values as input into the subject via the IObserver
methods (OnNext()
, OnCompleted()
and OnError()
) and that you can subscribe to the Subject via the IObservable.Subscribe()
method to get the output from the Subject. The Subject itself can do some transformation with the values that are pushed into it, can store the values and is able to take responsibility of what happens if someone subscribes to it. Subjects act as storage as well. When values are flowing into the Subject it can store them (or only the last or some transformed value, …) and when someone subscribes it can return all stored values (or only the last etc.). That means that e.g. an asynchronous operation needs not to be executed multiple times when using Subjects. The return value is stored in the Subject and can be extracted everytime a client subsribes to the Subject (independent of the moment of the subscription).
Dependent on the intent of the Subject, Rx comes with several implementations that differ in their transformation and output behavior:
AsyncSubject<T>
: This subject is used for asynchronous operations where only one value is expected as result. Thus the AsyncSubject
remembers only the last value.
BehaviorSubject<T>
: This subject always has a current value and fires everytime the value changes. Thus it’s kind of the INotifyPropertyChanged
event.
EventSubject<T>
: This subject corresponds to an event stream and thus will never invoke OnError()
or OnCompleted()
.
ReplaySubject<T>
: This subject is like a tape/video recorder. It records all events that are pushed into it and can be replayed. On replay it will return all events that have been recorded in exactly the same order and time interval in which they occurred.
Another really nice development is an Add-In for Visual Studio: Reactive Extensions Generator. It overcomes the problem that all types in the .NET Framework rely on .NET events and don’t offer methods or properties that return corresponding instances of IObservable
. This tool allows you to choose an assembly and it generates extension methods for all .NET events that it finds on the components of the assembly. Those methods will return the Observable pendants for those events instead. Really impressing stuff and very timely! Single drawback: it can be used only with Visual Studio 2010 and .NET 4.0.
So to sum up again: I think Rx is valuable in many situations. First it’s a better pattern for reactive programming that unifies asynchronous programming (that normally returns just one value) and event-based programming (that typically has an infinite event-stream) and second it’s very strong when you want to compose (+ filter and transform) several event streams and when you want to build up and react to very special and complex events. Stay tuned for more information and examples on that in upcoming blog posts.