SYSK 381: How To Get One Callback When Multiple Async Services Calls are Completed

My current project uses Silverlight 4.0 and RIA services, and I quickly came to realize the benefits and the challenges of all DomainService calls being asynchronous.

Consider this scenario: a Silverlight client app needs to get some data, that requires multiple DomainService calls – it may be because upon “processing” the first resultset, the business rules require getting additional data, or, perhaps, it’s due to recursive implementation (parent/child situation).In my case, it was the latter, and getting all data in one swoop on the server wasn’t supported by the available API…or, to be more accurate, making it work this way would have required a lot more code and would have ended up with messier implementation, but, perhaps, better performance (we’ll be doing performance profiling soon and may end up going that route if performance difference is significant).

Anyway, to summarize, here is the problem I’m trying to address (diagram is simplified for clarity):

As you can see, given all the async calls, we have to add the logic to assure that the client’s callback function is only invoked when all the async calls in the façade returned, i.e. all data is there…

2.From the DataServiceFacade.GetData1 method, create an instance of the notification context, and pass it along

publicpartialclassDataServiceFacade

{

publicstaticvoid GetData1(Action<ResultType> callback)

{

NotifyClientAction<ResultType> ctx =

newNotifyClientAction<ResultType>(callback);

ctx.OperationStarted();

// Now call the DataService.GetData1

// asynchronously and pass ctx as ‘UserState’

}

publicstaticvoid GetData1CallBack(LoadOperation<Data1Type> loadOp)

{

INotifyClientAction ctx = loadOp.UserState asINotifyClientAction;

// Loop processing results, call GetData2 as needed

ctx.OperationCompleted();

}

privatestaticvoid GetData2(..., INotifyClientAction ctx)

{

ctx.OperationStarted();

// Call the DataService.GetData2

// asynchronously and pass ctx as ‘UserState’

}

publicstaticvoid GetData2CallBack(LoadOperation<Data2Type> loadOp)

{

INotifyClientAction ctx = loadOp.UserState asINotifyClientAction;

// Loop processing results, call other methods as needed

ctx.OperationCompleted();

}

}

3.Remember to set ctx.Result to the data to be returned to the client in the appropriate place

NOTE: with RIA services (at least as of the time of writing this block), a DomainService instance can only be instantiated from the same thread (or you’ll get runtime errors)…Therefore, the code above, is not written to be thread-safe.Add locking as required, if you expect to use it in a multi-threaded execution scenario.