Rx (Reactive Framework) Can Improve UI Responsiveness

By John at November 24, 2009 14:51
Filed Under: Techy

I’ve been soaking up all the new Rx stuff coming out of Microsoft recently.  Basically it takes the concept of IEnumerable and flips it around into a type IObservable (gotta love duality…).

One of the areas in myOSity I’ve not been entirely satisfied with is the real-time search capability in the File System dialogs.  The feature allows you to type keywords into a text box, and the file list updates below in real-time.  However, this was previously entirely synchronously, such that long searches would hang the UI thread and cause unseemly lag in the responsiveness of the keyboard input.

The general format of this old method was like so:

  1. _app.tbautoSearchByTags.TextChanged += (sender, _) =>
  2.        {
  3.            var tb = (TextBox)sender;
  4.            FileSystemService.Current.VM.SearchCriteria = tb.Text;
  5.            FileSystemService.Current.VM.FilterBySearch();
  6.        };

 

Pretty standard stuff:  I subscribe to the event handler of the textbox’s TextChanged event, and then run my search query, feeding in the the .Text property of the TextBox.   This however, yields the laggy responsiveness that is so undesirable.

What I want to do is to only call my search function when the user has paused their typing for some period of time (.5 seconds, for example).  I could write my own timer logic, but as you will see, Rx handles this much more elegantly and in a much more composable way…

  1. var textObserver = (from text in Observable.FromEvent<TextChangedEventArgs>(_app.tbautoSearchByTags, "TextChanged")
  2.                     select text).Throttle(TimeSpan.FromSeconds(.5));
  3. _searchObserver = textObserver.Subscribe(textChangedEvent =>
  4. {
  5.     var tb = (TextBox)textChangedEvent.Sender;
  6.     FileSystemService.Current.VM.SearchCriteria = tb.Text;
  7.     FileSystemService.Current.VM.FilterBySearch();
  8. });

 

There are two main pieces to the above code.  First I am defining an IObservable (textObserver), which is a lazy Linq query.  You’ll also notice the extension method .Throttle, which prevents the observable from firing any data to the observer unless the given time has passed without any events occurring.  Said another way, the event stream from the TextChanged event must be quiet for .5 seconds before any observers will receive data.  Neat!

The second piece instantiates the observer via the .Subscribe extension.  Here I’m using a lamba to create an anonymous observer.

Now with the Rx magic in place, my UI is not making wasteful calls to the search function, but only when the user is “finished” providing input.  Improvements are still possible.  For example, I could make the search function asynchronous, and implement IObservable<T> on it.  This will help free up the UI thread even further while the search function does it’s work, and only return the result when complete. 

Comments are closed

What is myOSity?

myOSity is a On-Demand Operating System that runs in your browser.  You can run applications, work with files, keep in touch and share things with your friends, and more.  The goal of myOSity is to combine the best aspects of operating systems and social networking, while hopefully leaving out all the annoying stuff.

Curious?

To check out myOSity for yourself click here.

Have a game or other Silverlight project that you want to become part of the growing list of applications on myOSity? Contact Me for details.

Join The Team!

Currently looking for other developers interested in being a part of the project.  Contact Me for details or read this post.

About John

I am the founder and lead designer of myOSity.com.  I've been a technologist, in one form or another, for over 20 years.

Protected by Commentor
0 comments approved
4 spam caught
Since December 1, 2008
Powered by Spam Counter