Reactive Framework Subscribing to Events by ThinqLinq

Reactive Framework Subscribing to Events

Previously in my Reactive framework series, we saw how to create and subscribe to ongoing observable objects. While there are a number of cases where you would want to create your own observable type, often you simply want to compose reactive sequences in response to events raised by other means. Recently, I came across a simple example that can  show you how easy it is to subscribe to event and add functionality through the Reactive Framework’s extension methods.

In this scenario, I needed to update a list of most recently used files in real time. Whenever a new file was added , modified or deleted from a directory, I wanted my UI list to reflect this change. I’ve long known about the FileSystemWatcher class in Windows Forms. It is able to listen for create, change, delete and modify events in a specified file path and let us know when the file changes. Using Rx, we can create an observable using the following:


   Dim createWatcher As New FileSystemWatcher With {.Path = "C:\Temp", .EnableRaisingEvents = True}
   Dim createdEvent = Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Created")

Using the Observable.FromEvent, we indicate that we want to watch for events with the specified name (Created) from the supplied instance object (createWatcher). With this observable, we can now perform other operations on the resulting events. We’ll use the “Do” method to perform an action (refreshing the file list). Before we do this action on the UI, we’ll need to make sure to synchronize back to the UI thread:


    Dim AllEvents = Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Created").
                    ObserveOnDispatcher.
                    Do(Sub(fsArgs) RefreshFileList()).
                    Subscribe

This would be fine if we only wanted to watch for the events when the file is first created. However, in a Most Recently Used (MRU) list, we want to also know when a file is changed or deleted. Rather than wiring up separate handlers for each of these events, we can use the Merge method to listen to any of these events regardless of which event handler they came from:


    Dim AllEvents = Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Created").
                    Merge(Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Changed")).
                    Merge(Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Deleted")).
                    ObserveOnDispatcher.
                    Do(Sub(fsArgs) RefreshFileList()).
                    Subscribe

One of the great things about the Reactive Framework is the ability to inject functionality into the event pipeline easily. For example, if we want to avoid responding to multiple events on the same file, we could inject the DistinctUntilChanged method as follows:


    Dim AllEvents = Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Created").
                    Merge(Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Changed")).
                    Merge(Observable.FromEvent(Of FileSystemEventArgs)(createWatcher, "Deleted")).
                    DistinctUntilChanged.
                    ObserveOnDispatcher.
                    Do(Sub(fsArgs) RefreshFileList()).
                    Subscribe

Quick and easy (and elegant as well.) If you want to try this out, download RX_Wpf in the files section here and run the FileWatcher.xaml file.

Posted on - Comment
Categories: VB Dev Center) - Rx) -
comments powered by Disqus