- Silverlight Best Practices: Asynchronous Programming
- Using Action for an Event Façade
- Using the Asynchronous Programming Model (APM)
- The Problem: Nested Service Calls
- Summary
Using Action for an Event Façade
What really happens during the course of the asynchronous call is that the call is initiated, time passes, and then the result comes back as either an error (a failed call for some reason) or a result (a successful call). This is very easily modeled in C# for the addition web service by using the following signature:
void Add(int x, int y, Action<Exception, int> result)
The signature clearly provides the input parameters (two integers) and a delegate to call with the result, which will include an Exception object and an integer. It is presumed that if the Exception object is not null, then the call was not successful and the integer value is ignored. The implementation looks like this:
public delegate void ResultFromAdd(Exception exception, int result); public void Add(int x, int y, ResultFromAdd result) { var client = new HostServices.MyServicesClient(); client.AddCompleted += client_AddCompleted; client.AddAsync(x, y, result); } void client_AddCompleted(object sender, HostServices.AddCompletedEventArgs e) { var result = (ResultFromAdd) e.UserState; if (e.Cancelled) { result(new Exception("The call was cancelled."), 0); return; } if (e.Error != null) { result(e.Error, 0); return; } result(null, e.Result); }
Now calling the service is simpler and doesn’t require a method just to process the result because it can be in-lined using a lambda expression:
public void CallService() { Add(1, 2, (ex, result)=> Debug.WriteLine("1 + 2 = {0}", result)); }
This is also easier to test and mock because in the test scenario, the implementation of the method can simply perform the test function and immediately call the delegate with the desired test result.