Welcome to irritatedVowel.com Sign in | Help

POKE 53280,0: Pete Brown's Blog

Silverlight, WPF, Woodworking, .NET Programming, CNC, Nature, and other topics.
Pete is an MVP for Silverlight Click here to view the MVP profile.

A Microsoft Silverlight MVP and INETA Speaker, Pete Brown writes on a number of topics including Silverlight, WPF, .NET, woodworking and working as a consultant in the DC area. read more

Subscribe

Subscribe to my feed
Add to Technorati Favorites

Community Events



Applied Information Sciences - My Employer

who's online

AddThis Social Bookmark Button

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

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 :)

  Add to Technorati Favorites
Posted: Thursday, June 26, 2008 9:41 PM by Pete.Brown

Comments

Nico said:

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
# June 27, 2008 3:08 AM

Van Ice said:

Nice article, looking forward to part II. Any plans to put a a sample app to detail the thought process.
# June 27, 2008 5:35 AM

Pete.Brown said:

@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.

# June 27, 2008 9:43 AM

Pete.Brown said:

@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.

# June 27, 2008 10:00 AM

POKE 53280,0: Pete Brown's Blog said:

In my previous post , I discussed how to chain service calls. One question I received on that was how
# June 27, 2008 11:05 AM

Community Blogs said:

In my previous post , I discussed how to chain service calls. One question I received on that was how
# June 27, 2008 12:37 PM

Community Blogs said:

Jaime Rodriguez on DeepZoom, Pete Brown on on Publish/Subscribe pattern in SL, Shawn Wildermuth on XAML
# June 27, 2008 6:15 PM

POKE 53280,0: Pete Brown's Blog said:

In the previous two parts of this article (I had planned only 2 parts total, but this ended up a three-part
# June 30, 2008 11:26 PM

Bryan Reynolds said:

Greate post! I plan on using this. Thanks!
# July 11, 2008 12:09 PM

POKE 53280,0: Pete Brown's Blog said:

My primary Silverlight project for the past couple months has been the Facebook application I’ve been
# September 21, 2008 2:26 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the text you see in the image:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS