API's that Suck

December 2, 2009

Why closures are important to GUI developers

Filed under: Uncategorized — Grauenwolf @ 9:51 pm

Lets say you have some code that calls the database and processes the results. Here is a simple in-line version.

  1. private void PerformDataBaseSearch()
  2. {
  3.     m_Progress.Visibility = Visibility.Visible;
  4.     m_SearchButton.IsEnabled = false;
  5.  
  6.     var errorKey = (MPSPortfolioProcessErrorType)m_ErrorTypeSearchBox.SelectedItem;
  7.     var accountNumber = this.m_AccountSearchBox.Text;
  8.  
  9.     List<MpsPortfolioError> resultList = null;
  10.  
  11.     try
  12.     {
  13.         resultList = MpsPortfolioError.Search(Context.FisDatamapper, errorKey, accountNumber);
  14.         InternalControlSetup(resultList);
  15.     }
  16.     catch (Exception ex)
  17.     {
  18.         Context.Logger.DisplayException(ex, "Email Error Search has failed.");
  19.     }
  20.     m_Progress.Visibility = Visibility.Hidden;
  21.     m_SearchButton.IsEnabled = true;
  22.  
  23. }

Since they touch the user interface, Lines 3 thru 7 and 14-21 have to be executed on the GUI thread. Line 13, which actually calls the database, shouldn’t be on the GUI. Normally the way we would fix this is to break up the function into three separate functions using threads and invokes to control where each part gets executed. In earlier versions of C# this was quite tedious and somewhat error prone.

With closures, this becomes downright simple.

  1. private void PerformDataBaseSearchAsynch()
  2. {
  3.     m_Progress.Visibility = Visibility.Visible;
  4.     m_SearchButton.IsEnabled = false;
  5.  
  6.     var errorKey = (MPSPortfolioProcessErrorType)m_ErrorTypeSearchBox.SelectedItem;
  7.     var accountNumber = this.m_AccountSearchBox.Text;
  8.  
  9.     List<MpsPortfolioError> resultList = null;
  10.  
  11.     var asyncSearch = new BackgroundWorker();
  12.     asyncSearch.DoWork += (arg1, arg2) =>
  13.         {
  14.             resultList = MpsPortfolioError.Search(Context.FisDatamapper, errorKey, accountNumber);
  15.         };
  16.  
  17.     asyncSearch.RunWorkerCompleted += (arg1, arg2) =>
  18.         {
  19.             if (arg2.Error == null)
  20.                 InternalControlSetup(resultList);
  21.             else
  22.                 Context.Logger.DisplayException(arg2.Error, "Email Error Search has failed.");
  23.             m_Progress.Visibility = Visibility.Hidden;
  24.             m_SearchButton.IsEnabled = true;
  25.         };
  26.  
  27.     asyncSearch.RunWorkerAsync();
  28. }

Here is how to read the new breakdown of the function.

  • Lines 1 thru 11 haven’t changed, they all run synchronously on your GUI thread.
  • Lines 12 thru 15 define an anonymous function that will run asynchronously on a background thread.
  • Lines 17 thru 25 define an anonymous function that will run asynchronously on the GUI thread, once the background thread is done.
  • Line 27 says all the asynchronous functions have been defined and processing can begin.

Now that I’ve shown you how anonymous functions can be used to keep the logical flow of a procedure while the physical flow is broken up into threads, lets talk about closures themselves. We use one closure in this, the resultList variable. It is defined in the synchronously function, set by the background function, and read by the asynchronous GUI function. All three functions get access to this variable, but nothing else does so we don’t have to worry about synchronization.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: