Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Using Pub/Sub and the Observer Pattern in Silverlight 2 (Part 1 of 2) - Async Service Call Chaining

Pete Brown - 26 June 2008

The Publish and Subscribe pattern (which uses the Observer Pattern in .NET - more info here) is one of those patterns we use all the time while thinking nothing of it. In .NET, we get the concrete implementation via events and delegates.

By abstracting it out just a little and applying concepts from other bus patterns, we gain a ton of flexibility and can use it for more specialized messaging than button click events. In Silverlight applications, in the client code, I tend to use it for two things:

  • Providing a means by which different parts of the application can notify each other of changes without requiring tight coupling
  • Providing a centralized mechanism for controlling navigation. This is really a variation on the first, but I break it out as I usually do when implementing. I'll post about this topic in the follow-up post

The first one is usually handled by a class named EventBus or similar. (EventBus is a well-known name used by technologies in the java world, biztalk etc., so I recommend that. I was encouraged to see a colleague at another firm used the same name in an application we did for a demo, so it's likely a pretty common name and pattern.)

image

Here's a simple example from my current project. This part is used for notifying various parts of the application that data has been loaded from async calls to web services:

public static class EventBus
{
    public static event EventHandler ConfigurationLoaded;
    public static event EventHandler MediaPageContentLoaded;
    public static event EventHandler EventPageContentLoaded;
    public static event EventHandler GeneralPageContentLoaded;
    public static event EventHandler UserInformationLoaded;

    #region Event Raising

    public static void OnConfigurationLoaded(object sender, EventArgs e)
    {
        if (ConfigurationLoaded != null)
            ConfigurationLoaded(sender, e);
    }

    public static void OnUserInformationLoaded(object sender, EventArgs e)
    {
        if (UserInformationLoaded != null)
            UserInformationLoaded(sender, e);
    }

    public static void OnMediaPageContentLoaded(object sender, EventArgs e)
    {
        if (MediaPageContentLoaded != null)
            MediaPageContentLoaded(sender, e);
    }

    public static void OnEventPageContentLoaded(object sender, EventArgs e)
    {
        if (EventPageContentLoaded != null)
            EventPageContentLoaded(sender, e);
    }

    public static void OnGeneralPageContentLoaded(object sender, EventArgs e)
    {
        if (GeneralPageContentLoaded != null)
            GeneralPageContentLoaded(sender, e);
    }

    #endregion
...
}

I store all the loaded data in a singleton ApplicationData class which serves both as the local data cache and the interface to the data web service. Here's the code in that class:

public void LoadUserInformation(string platformSpecificSessionKey)
{
    ConfigurationServiceClient client = new ConfigurationServiceClient();
    client.GetUserInformationCompleted += 
        new EventHandler<GetUserInformationCompletedEventArgs>(client_GetUserInformationCompleted);
    client.GetUserInformationAsync(platformSpecificSessionKey);
}

void client_GetUserInformationCompleted(object sender, GetUserInformationCompletedEventArgs e)
{
    _userInformation = e.Result;

    ((ConfigurationServiceClient)sender).CloseAsync();

    EventBus.OnUserInformationLoaded(this, new EventArgs());
}
(In woodworking magazines, they often write "safety guards removed for clarity" in articles where someone is doing something dangerous. I'll say the same here, just don't call me on it :) "Exception Handling Removed for Clarity")

If you're struggling with a way to chain your async service calls and want to do the right thing by not using WaitOne or otherwise blocking the UI thread, this is one way that can help you out. Have your client-side service interface class be both a publisher and a subscriber and chain your web service calls via event handlers. You could, of course, just chain inside the same functions, but that gets ugly once you have more than a couple levels.

Here's the code that chains the remaining data calls that are dependent on the call to load the user information. The three calls in here all need the information from the user data web service before they can proceed.

EventBus.UserInformationLoaded += new EventHandler(EventBus_UserInformationLoaded);
...
void EventBus_UserInformationLoaded(object sender, EventArgs e)
{
    // we can only get the other information once we have the user
    // information available

    ApplicationData.Current.LoadEventsPageData();
    ApplicationData.Current.LoadMediaPageData();
    ApplicationData.Current.LoadGeneralPageData();
}

Note that I don't use this architecture for everything - just information the rest of the application is interested in. I also make sure to translate the events into something meaningful before publishing. For example, the rest of the application is probably not interested in the click event of the "ApplyOptions" button, but it very likely is interested in an OptionsChanged event.

Now, there are lots of other things you may want to notify the rest of the application about. One is the example above where options are changed by the user and you need to do something like change screen colors or font size. Another is when you want to navigate from one page to another. I'll cover using this pattern for navigation in the next post.

One last note: this is by no means specific to Silverlight. I've used this on Windows Forms and other client technologies in the past. It just happens that Silverlight is my newest toy :)

             
posted by Pete Brown on Thursday, June 26, 2008
filed under:              

5 comments for “Using Pub/Sub and the Observer Pattern in Silverlight 2 (Part 1 of 2) - Async Service Call Chaining”

  1. Nicosays:
    Hello Pete
    Very nice post on the observer pattern. I'm using something similar in our application. But I'm strugling a bit with a related problem. What you've got is triggering three actions (loading Eventspage, mediapage...) after one is complete. But what I'm looking for is a nice way to do the opposite. In my concrete case multiple subsequent calls are made to a WCF service to retrieve data. I would like to show a busy screen until all calls have 'completed'. Do you have any idea of a nice way to do this? Any suggestions are welcome :-) Nico
  2. Pete Brownsays:
    @Nico Great question. That is definitely something I left out by accident in this post. I'll put together another post on that topic shortly, as I have that same challenge in the application I'm building, and have already written code to handle it.
  3. Pete Brownsays:
    @Van Ice: The code I'm showing is pulled directly from an application I'm building. Time permitting, I'll put together a sample showing just these practices. I'm not sure yet if the source for the entire app will be released, but I'll post here if so.

Comment on this Post

Remember me

5 trackbacks for “Using Pub/Sub and the Observer Pattern in Silverlight 2 (Part 1 of 2) - Async Service Call Chaining”

  1. POKE 53280,0: Pete Brown's Blogsays:
    In my previous post , I discussed how to chain service calls. One question I received on that was how
  2. Community Blogssays:
    In my previous post , I discussed how to chain service calls. One question I received on that was how
  3. Community Blogssays:
    Jaime Rodriguez on DeepZoom, Pete Brown on on Publish/Subscribe pattern in SL, Shawn Wildermuth on XAML
  4. POKE 53280,0: Pete Brown's Blogsays:
    In the previous two parts of this article (I had planned only 2 parts total, but this ended up a three-part
  5. POKE 53280,0: Pete Brown's Blogsays:
    My primary Silverlight project for the past couple months has been the Facebook application I’ve been