views:

66

answers:

2

I'm working on this Silverlight 3.0 Project that is completely filled with Async Calls to a Web Service. At the Main Page it fetches some needed data in order for the application to work correctly using 3 Async Calls. Right now the application does not disable any controls while executing those calls meaning a user can interact with it without that needed data. I need to disable the whole grid and only after all 3 Async calls are finished then and only then enable the grid.

What's the best practice for doing this.

These are my calls:

client.GetAllAsync();
client.GetAllCompleted += new EventHandler<GetAllCompletedEventArgs>(client_GetAllCompleted);

client.GetActualAsync();
client.GetActualCompleted += new EventHandler<GetActualCompletedEventArgs>(client_GetActualCompleted);

client.GetSomeAsync();
client.GetSomeCompleted += new EventHandler<GetSomeCompletedEventArgs>(client_GetSomeCompleted);
A: 
  1. Make a unit of work item in your silverlight
  2. This UOW raises an event when finished
  3. Bind that event to your GUI code
  4. Use signaling or a simple counter in your unit of work to raise the 'finished' event.
Ramon
+1  A: 

Seems lot a lot of work just to queue some user interactivity.

I typically provide an application-wide interface:

public interface IAppGlobalState 
{
   void BeginAsync(); 
   void EndAsync(); 
}

In the implementation, I'll do this:

public partial class MainShell : UserControl, IAppGlobalState 
{
   private int _queue; 
   private object _mutex = new Object();

   public void BeginASync()
   {
      Monitor.Enter(_mutex);
      if (_queue++ == 0)
      {
         VisualStateManager.GoToState(this, "BusyState", true);
      }
      Monitor.Exit(_mutex);
   }

   public void EndAsync()
   {
      Monitor.Enter(_mutex);
      if (--_queue == 0)
      {
         VisualStateManager.GoToState(this, "IdleState", true); 
      }
      Monitor.Exit(_mutex);
   }
}

Of course if you have heavy multi-threading then you'll use Interlocked on those but most of the time you'll be invoking it from the same thread. Then, you simply do:

GlobalState.BeginAsync();
client.FirstAsyncCall();

GlobalState.BeginAsync();
client.FirstAsyncCall();

And then on the return, just:

GlobalState.EndAsync();

If you have nested calls, no problem, this method unwinds them.

Jeremy Likness