Microsoft DevLabs its been cooking some very very cool extensions called the Reactive Extensions (Rx for short) to make the asynchronous programming model more simplistic by using the observer design pattern more efficiently through code.

Since the beginning the observer pattern it's been supported by the framework using traditional delegates and event handlers. Previous to the CLR 4.0, the was no IObserver or IObservable interfaces as part of the .NET Framework Class Library (FCL) and it was certanly one of the MOST notable missing legs of it. This was looooong overdue; almost every other main stream language provides classes to implement the pattern and now we can include the .NET languages as well.

But let's jump back into Rx. These guys took la crème de la crème, some duality concepts, object and function composition, the observer pattern and the power of LINQ and created one set of AWESOME extensions. In their own words:

Rx is a library for composing

asynchronous and event-based programs

using observable collections.

In the synchronous world communication between processes does not have any buffer, and processes wait until the data between them has been completed computed and transferred; this means that you could have a sluggish DB slowing the entire process down or any link on the 2-way communication for that matter (network card, OS, firewall, internet connection, web server, db server, etc).  In the asynchronous programming world instead of waiting for things to be finished, your code stands from the point of view of a subscriber. You are waiting for somebody to notify you there is something there to be taken immediately, and then you can take action on the subject. This is very convenient because you are never blocking any calling thread and your programs (specially those with a UI thread) are very responsive never die waiting for a response or consuming CPU cycles. There are many tools, namespaces and helper classes .NET provides out of the box to support async programming such as the ThreadPool, BackgroundWorker, Tasks, etc. What is the problem then? What's the reason for Rx existence?

The basic problem the Rx team is trying to solve is that was of the lack of clarity and simplicity that asynchronous model has attached to it. Working today in an async world is way too complicated, you have to create a bunch of "support garbage code" (as I call it) just to perform the simple task of waiting for the async call to return so you can do something with the result. It resolved the issues with .NET events, such as their lack of composition, resource maintance (you have to do -= after you finish), the event args always acts as a unsafe container for the real data source triggering the event, and lastly you cannot pass around in an object an event and manage it elsewhere. Events are not first-class .NET citizens, they do not share the same benefits are regular reference objects, you cannot assign it in a field or put it in an array, yadayada.

A simple example is suppose you have a combobox and want auto-complete behaviour in the combobox, but your word dictionary is on a remote web service and you want the user to see the first 20 matches in the dictionary filtering as they type (like any other mayor browser's search box today). Let's see what we have:

On the server

[sourcecode language="css"] [WebMethod Description="Returns the top 20 words in the local dictionary that matches the search string"] public List<string> FindTop20Dict(string searchString, string matchPattern) {...} [/sourcecode]

Now on the client.

[sourcecode language="csharp"] /*Then on the client we have to implement the TextChanged event and then 2 timers with their ticks (to give some room between keypress and keypress, say 0.5 seconds) and then we have to make sure we cancel the previous call if a new keypress is made. Manually. In a comparison loop using the timers :| Also you have to check if the text actually changed, because if you do Shift+Left and type the same selected char, the event will fire even when the text DID NOT CHANGED... ufff a lot of things to consider here and then we have to assign the result to the combobox items. All this while we had a thread locked waiting for the result from the server. You get the idea of how hard it is and how error prone*/ [/sourcecode]

I did not write the actual code because it'll take quite a bit of chunk of the post, but what I can do is to write the code that'll accomplish the same thing in the client using Rx extensions.

[sourcecode language="csharp"] //Grab input from textchanged var ts = Observable.FromEvent<EventArgs>(txt, "TextChanged"); var input = (from e in ts select ((TextBox)e.sender).Text) .DistinctUntilChanged() .Throttle(TimeSpan.FromSeconds(0.5)); // //Define the syntax of your observer var svc = new MyWebService(); var match = Observable.FromAsyncPattern<string, string, List<string>> (svc.BeginFindTop20Dict, svc.EndFindTop20Dict); var lookup = new Func<string, IObservable<List<string>>>(word => match(word, "prefix")); var result = from term in input from words in lookup(term) select words // //Subscribe and wait will the magic happens using (result.Subscribe(words => { combo.Items.Clear(); combo.Items.AddRange(result.ToArray()) ; } [/sourcecode]

As you can see using Rx it is possible to read what is going on in plain English, it is more efficient (since it is optimized and using best practices) and it'll make your code more elegant and legible when coding in the async world.

If you want to find out more about Reactive Extensions (Rx) check out the links:

Rx channel in Channel 9 at: http://channel9.msdn.com/tags/rx

Rx DevLabs page: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

Rx Team Blog: http://blogs.msdn.com/b/rxteam/

As of today 11/17/2010 you can download the Rx extensions from DevLabs and play and create beautiful code with this extensions. Give them a try and let's just hope they are include in .NET 4.5 as the standard way of working with the asynchronous programming model.

Comment