views:

444

answers:

3

Most of the code I've written in .NET to make REST calls have been synchronous. Since Silverlight on Windows Phone only supports Async WebClient and HttpWebRequest calls, I was wondering what a good async pattern is for a Class that exposes methods that make REST calls.

For example, I have an app that needs to do the following.

  1. Login and get token
  2. Using token from #1, get a list of albums
  3. Using token from #1 get a list of categories
  4. etc

my class exposes a few methods:

  1. Login()
  2. GetAlbums()
  3. GetCategories()

since each method needs to call WebClient using Async calls what I need to do is essentially block calling Login till it returns so that I can call GetAlbums().

What is a good way to go about this in my class that exposes those methods?

+3  A: 

It really depends on what you want to do with this information. If for instance you are attempting to display the list of albums/categories etc, one way to model this would be to

  1. Have one or more classes which implements the INotifyPropertyChanged interface, and are used as data sources for your views (look at the files under the Models folder in a new PhoneListApplication for an example)
  2. Start an async operation to login and get the token, have the async method's callback store the token for you and call a function which will start an async operation to get list of albums and categories.
  3. The callback for the async operation to get a list of albums/categories can update an ObservableList (by adding items to it). I'd imaging you have one class each for albums and categories, each with an observable list. Anyways, once you are done adding, just call NotifyPropertyChanged with the name of the property you changed, and your data should show up.

There is an obvious problem with cases where you want to wait and not proceed until you receive something back over the network (for instance if you want to keep the login page around until you know that you have successfully authenticated). In this case you could just change the page in the async callback.

You could obviously also do something fancier and have a thread wait for an event set by the async callback. I recommend not have the UI thread do this, since it limits your ability to have things like timeouts, and is generally very messy.

Aurojit Panda
+4  A: 

You might take a look at the Reactive (Rx) framework extensions:

http://www.leading-edge-dev.de/?p=501

http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html

[edit: ooh - found a good link:] http://rxwiki.wikidot.com/101samples

They provide a way to "sequence" events, acting only upon certain conditions met - for example, say you had a method "AuthenticationResult Authenticate(string user, string pass)"

You could do something like:

var foo = Observable.FromAsyncPattern<string, string, AuthenticationResult>
    (client.BeginAuthenticate, client.EndAuthenticate);
var bar = foo("username","password");
var result = bar.First();

Effectively turning an asynchronous method to a synchronous one. You can extend this to include "chaining":

var bar = foo("username", "password")
    .Then(authresult => DoSomethingWithResult(authresult));

Neat stuff. :)

JerKimball
+1  A: 

We wrote our client-side service layer with all async function signatures that look like this:

public void MyFunction(
  ArtType arg, 
  Action<ReturnType> success, 
  Action<FailureType> failure);

The service code does an async call to the web service, and when that returns it calls the success callback if the call was successful, and the failure callback if there was a fault/exception. Then the calling code kinda looks like this:

MyServiceInstance.MyFunction(
  blahVar,
  returnVal => UIInvoker.Invoke(() => 
    {
      //some success code here
    }),
  fault => UIInvoker.Invoke(() => 
    {
      //some fault handling code here
    }));

(UIInvoker is just a utility that dispatches back to the UI from a background thread.)

Jason Jackson