Rx requires a slightly different way of thinking about asynchronous behaviour and events. The fundamental concept of Rx is based around the idea of there being something that is observable that generates a sequence of things for an observer to observe. The other things to be aware of about the way that Rx works are:
- It’s a push model — the observable instance pushes information to the observer instance.
- The observer can filter the information that it receives by using LINQ queries.
Arrays in .NET implement the IEnumerable interface that enables you to iterate over the array, pulling each item from the array:
For this example we can convert the array to an observable sequence that implements the IObservable interface:
We can then observe this sequence by subscribing to the IObservable instance like this:
This overload of the Subscribe method receives each number pushed at it by the observable sequence, and the three lambda expressions allow you to:
- Handle each item in the sequence as it arrives.
- Handle any exceptions raised.
- Handle the end of the sequence.
Handling EventsWriting code to handle events is a very common task. The following code shows how you might prevent a user from entering non-numeric characters into a text box:
To do the same thing using Rx, you could do this:
Notice that you don’t need the KeyDown attribute in the XAML code for this approach to work.
The FromEvent method enables you to treat an event as an observable sequence. This example also shows how you can use a LINQ expression to filter/query the items in the observable sequence; here you are only selecting non-numeric characters.
The Subscribe method here receives any non-numeric keystrokes in the textBox2 control, discards them and then updates a label control.
Running a Background TaskThe following example shows the outline to a standard approach to running a background task in a WPF application using a the Task class. See John Sharp’s post here for more background in the Task class and the Task Parallel Library.
One thing to note about this is the use of the Dispatcher.Invoke method to update the UI from a background thread.
To achieve the same results using Rx, you could use the following code:
This example responds to a click event using the same technique as the previous Rx example, and then runs the background task by using the Observable.Start method. The ObserveOnDispatcher method ensures that the observer runs on the dispatcher thread so that it can safely update the UI.
Synchronizing TasksJohn Sharp’s post here also described how you could synchronize several background tasks using the WaitAll and WaitAny methods in the Task Parallel Library. You can do a similar thing using Rx like this:
This example uses the Observable.Start method to define two background tasks, each of which returns an integer result. The ForkJoin method enables you to wait for both tasks to complete, and the example code then prints a “Done” message using the Finally method. You can then access the results of all the background tasks by using the First method (First because you want the first, and only set of results from the tasks sequence).
There’s an interesting discussion about the differences between running multiple background tasks with Rx and using the Task Parallel Library here: http://social.msdn.microsoft.com/Forums/en-US/rx/thread/12d3f79a-0a53-4854-976e-5fa0d86f01ee/.