Undergraduate student of Department of Informatics, University of Athens. Microsoft Student Partner. Nikos is a DZone MVB and is not an employee of DZone and has posted 5 posts at DZone. View Full User Profile

Visual Studio async CTP with Silverlight

01.06.2011
| 10714 views |
  • submit to reddit

Well, silverlight applications have a lot of asynchronous operations (WCF, WCF RIA operations, etc.), I recall a project in which I had to do this procedure: download a set of users asynchronously, if the download was not successful, do some finishing operations, else download a set of customers, if the download was not successful, do some finishing operations, else download a set of streets….A HELL OF DIFFERENT FUNCTIONS in a class for just a bunch of simple operations.

Hopefully, visual studio async CTP is here to solve these kind of problems once and for all. It is a way to make asynchronous operations look like they are synchronous. For more information have a look here. You can download it from here.

Together we are going to see two examples, one using a simple WCF service and one using WCF RIA services.

Simple WCF service

Lets create a wrapper class for bing maps services. In this class we’ll add a function that takes an address name as a parameter and returns a Geocode result. First, if you downloaded the library correctly, then you should have a folder that contains .dll files which are appropriate for the async CTP to run. Add a reference to the AsyncCtpLibrary_Silverlight library and add a new class with the following function:

   1: public Task<GeocodeResult> GetGeocode(string address)

2: {

3: GeocodeServiceClient service = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");

4: TaskCompletionSource<GeocodeResult> task = new TaskCompletionSource<GeocodeResult>();

5:

6: GeocodeRequest request = new GeocodeRequest();

7: request.Credentials = new Microsoft.Maps.MapControl.Credentials();

8: request.Credentials.ApplicationId = Credentials.Key;

9:

10: request.Query = address;

11:

12: service.GeocodeCompleted += (s, e) =>

13: {

14: if (e.Error != null || e.Result.Results.Count == 0)

15: task.TrySetException(new Exception("Η περιοχή \"" + address + "\" δε βρέθηκε"));

16: else if (e.Cancelled == true)

17: task.TrySetCanceled();

18: else

19: task.TrySetResult(e.Result.Results[0]);

20: };

21:

22: service.GeocodeAsync(request, address);

23:

24: return task.Task;

25: }

You may see some new stuff here:

  • Task<GeocodeResult>

It’s the class that is used to wait for an asynchronous operation to finish.

  • TaskCompletionSource<GeocodeResult>

A call to an asynchronous WCF service function lets us pass a user state parameter, so we pass this kind of object as a user state and gets filled when the function ends (task.TrySetResult(e.Result.Results[0]);) ).

What is finally returned from this wrapper function is a task, lets see now how we can use it. A function that calls the previous wrapper function may look like this:

   1: private async void CalculateRoute()

2: {

3: GeocodeResult result = await _calculator.GetGeocode(address);

4: }

Here you can see two new keywords:

  • async

Each function that uses the async CTP must contain this keyword in its definition and must be void.

  • await

With this keyword we actually turn an asynchronous call into a synchronous one, more specifically, we wait for an asynchronous call to finish and take the object that returns.

I hope you like the async CTP because we just got warmed up !

 

WCF RIA Services

 

Well, usage of async CTP is a bit more complex with WCF RIA services, but thanks to Kyle McClellan, in this post he created an extension method for embedding the async CTP task in the RIA services contexts, and this extension method is the following:

   1: public static class OperationExtensions

2: {

3: public static Task<T> AsTask<T>(this T operation)

4: where T : OperationBase

5: {

6: TaskCompletionSource<T> tcs =

7: new TaskCompletionSource<T>(operation.UserState);

8:

9: operation.Completed += (sender, e) =>

10: {

11: if (operation.HasError && !operation.IsErrorHandled)

12: {

13: tcs.TrySetException(operation.Error);

14: operation.MarkErrorAsHandled();

15: }

16: else if (operation.IsCanceled)

17: {

18: tcs.TrySetCanceled();

19: }

20: else

21: {

22: tcs.TrySetResult(operation);

23: }

24: };

25:

26: return tcs.Task;

27: }

28: }

And now, we can call domain service context methods like this:

   1: MyContext context = new MyContext();

2:

3: LoadOperation<MyModel> operation = await context.Load<MyModel>(context.DownloadModelsQuery()).AsTask();

4: foreach (MyModel model in operation.Entities)

5: MessageBox.Show(model.Id.ToString());

This is all for today ! I hope you like the async CTP !! Happy new year and have a nice time !!



References
Published at DZone with permission of Nikos Printezis, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)