Observable.FromEventPattern discussed

I was actually looking through my past blog posts and noticed I’ve never published anything on Reactive Extensions (Rx). I actually have a draft “beginners” guide which I started a couple of years back, but never completed, so I may end up publishing that at a later date.

Note: The best resource for Rx information that I’ve found is Introduction to Rx, I’d definitely recommend you visit that site for complete and excellent documentation on Rx.

Okay, for this post I’m just going to focus on the FromEventPattern. Even though the syntax is pretty simple I have a habit of forgetting it everytime I come to use it, so as this blog is about refreshing my memory, I thought I’d write a blog post dedicated to this method.

Why use Rx instead of handling events in the conventional way?

One of the most obvious reasons to use Rx to handle events is that it can help stop those pesky memory leaks when we forget to unsubscribe to an event. Another reason is the IObservable returned from FromEventPattern is composable and we can filter events that we’re not interested in and/or marshal events from one thread onto another – for example when events are coming from a worker thread we might marshal them onto the UI thread.

Take a look at Observable.FromEventPattern Method to see the current syntax/overloads for this method.

I will not be covering all the overloads here but will instead look at the three I’ve used the most. So let’s get started…

FromEventPattern with an EventHandler which takes no EventArgs

In some cases you might have an event handler which doesn’t use EventArgs, for example

public event EventHandler Reverted;

in such a case we use the overload

public static IObservable<EventPattern<EventArgs>> FromEventPattern(
	Action<EventHandler> addHandler,
	Action<EventHandler> removeHandler)

So our code might look like this

var o = Observable.FromEventPattern(
   x => domainObject.Changed += x,
   x => domainObject.Changed -= x).
   Subscribe(_ => DoSomething());

FromEventPattern with standard event patterns (using the EventHandler class)

Building on the previous syntax…

In many cases, where the events that we want to subscribe to, use the “standard .NET event pattern”, (for example where the handler takes an EventArgs derived class) and were declared using the syntax

public event EventHandler<CellsInViewChangedEventArgs> CellsInViewChanged;

we will use this overload. Note: This version expects an EventHandler<> object.

public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(
	Action<EventHandler<TEventArgs>> addHandler,
	Action<EventHandler<TEventArgs>> removeHandler
)
where TEventArgs : EventArgs

To use this we simple supply the EventArgs derived type, for example

var o = Observable.FromEventPattern<CellsInViewChangedEventArgs>(
   x => grid.CellsInViewChanged += x,
   x => grid.CellsInViewChanged -= x).
   Subscribe(_ => DoSomething());

FromEvent pattern with standard event patterns (not using the Event Handler class)

Finally, for this post, in some cases we have events which do not use the EventHandler<> class, for example the WPF RoutedEvents use

public delegate void RoutedEventHandler(
   object sender, 
   System.Windows.RoutedEventArgs e)

In such cases we need to supply both the Delegate type and EventArgs type to the FromEventPattern, hence we use the syntax

public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(
	Action<TDelegate> addHandler,
	Action<TDelegate> removeHandler
)
where TEventArgs : EventArgs

our code will now look like this

var o = Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
   x => button.Click += x,
   x => button.Click -= x).
   Subscribe(_ => DoSomething());

More…

I don’t intend to cover all the possible uses of the IObservable which is returned by the FromEventPattern, but suffice to say (as mentioned earlier). We can ensure events are marshaled onto the thread which created the observable, so for example if we create this from the UI thread we can write

var o = Observable.FromEventPattern<ValuesChangedEventArgs>(
   x => server.ValuesChanged += x,
   x => server.ValuesChanged -= x).
   ObserveOn(SynchronizationContext.Current).
   Subscribe(_ => DoSomething());

here, the ObserveOn will ensure that the events that might be coming from a worker thread are marshaled onto the current thread. Obviously if this was created on the UI thread this will marshal back onto that thread.