(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Store apps with XAML and HTML: Handling asynchronous operations

(1 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   91
Comments:   9
More Articles
0 comments   /   posted on Apr 22, 2013
Categories:   Windows 8

Tweet

If you have been in touch with the new WinRT environment, you have met for sure a number of calls that use an asynchronous pattern to be accomplished. These usually are indicated by the "Async" suffix on the method name and they are much more frequent than expected due to the WinRT architecture. As a meaningful example, to open a simple and common message dialog, you have to use the ShowAsync method that is clearly, and unexpectly and asynchronous operation. Without focusing on the reasons of this choice that is mainly about performances and fluidity of the applications, it is clear that a language used to write Windows Store applications cannot omit to support this important pattern.

The hard way of the asynchronous programming

The asynchronous programming is not a totally new matter for developers. Since the birth of multithreaded systems, the need to handle multiple parallel threads is something that has been handled in a number of different ways and it has always been a difficult matter, reserved to skilled developers able to think about its implications.

But away from difficult matters, like concurrency, scheduling and other similar, the first point you met, when you handle one or more asynchronous tasks, is the way your code becomes hardly understandable. Usually the .NET Framework and other languages handles asynchronous operations with events and callbacks and they make "non-linear" the flow of your program. here a simple example demonstrating the concept I've expressed.

   1: function downloadFile(uri)
   2: {
   3:     var dummy = 0;
   4:     API.download(uri, handleFileDownloaded);
   5: }
   6:  
   7: function handleFileDownloaded(theFile)
   8: {
   9:     // do something with the file...
  10: }

The pseudo-code I wrote use a callback pattern that is usual to Javascript as well as other languages like C++. C# has additional ways to handle the same matter, like Begin-End pattern and delegates, but at the proof of facts they have the same drawback which derives directly from the fork of the flow. At the end the problem is that the flow starts in a point and ends in another and this is hard to handle because ot the loss of the state. In few words, the value of the "dummy" variable is not available to the body of the handleFileDownloaded method because out of its scope. This is usually handled in javascript inlining the functions that responds to a callback:

   1: function downloadFile(uri)
   2: {
   3:     var dummy = 0;
   4:     API.download(uri, 
   5:         function (theFile)
   6:         {
   7:             // do something with the file...
   8:         });
   9: }

Thanks to this syntax the "dummy" variable remain into its scope also into the anonymous function that receives the response and this helps to have a more linear flow in the code. The problem is exactly the same in C# where the callback may be an event handler and the anonymous function is usually a lambda expression but it isn't so much different in the way it is handled:

   1: private void DownloadFile(uri)
   2: {
   3:     int  dummy = 0;
   4:     API.Download(uri, 
   5:         theFile => 
   6:         {
   7:             // do something with the file...
   8:         });
   9: }

So, now let's say you have a number of subsequent calls to be accomplished one after the other and you rapidly go out of you mind following the nested callbacks. It's very crazy if you think about having to download a file, ask confirmation, save the file and present a message, given that all these operation should be made asynchronous in a Windows Store app:

   1: private void DownloadFile(uri)
   2: {
   3:     API.Download(uri, 
   4:         theFile => {
   5:             askConfirm(
   6:                 yn => {
   7:                     if (yn) saveFile(
   8:                         success => {
   9:                             sayOk(success ? "ok" : "ko",
  10:                                 () => {
  11:                                     // ok... we are out of brackets here...
  12:                                 });
  13:                         });
  14:                 });
  15:         });
  16: }

Javascript and C#, the two languages for HTML and XAML applications solves the problem with a similar approach, using a pattern based on an object that represents the asynchronous operation.

I made a promise...

Encapsulating an asynchronous operation in a object that represents it, have a strong advantage on the previous way. The object can be passed along a number of methods and each one can add its own part without really executing the operation until the end of the chain. While Javascript calls "promise" this object, in C# it goes under the name of Task, but at the basis they are pretty similar each other. Let's start with Javascript's promises; every asynchronous method returns an object that is an instance of WinJS.Promise. This is the object that encapsulate the asynchronous operation. The final receiver of the object can call two methods to wait for the task completion, "then" and "done".

   1: showDialogAsync: function (message, ok, fail)
   2: {
   3:     var dialog = new Windows.UI.Popups.MessageDialog(message);
   4:  
   5:     dialog.commands.append(new Windows.UI.Popups.UICommand(ok, null, true));
   6:     dialog.commands.append(new Windows.UI.Popups.UICommand(fail, null, false));
   7:  
   8:     return dialog.showAsync().then(
   9:         function (uiCommand) 
  10:         { 
  11:             return uiCommand.id; 
  12:         });
  13: },

In this example the "then" method is called on the showAsync() result. This passes the resulting uiCommand to the anonymous function and it extract the boolean value that indicates in the user pressed "ok" or "fail". As a result, "then" returns another promise and it is returned to the caller. So the caller can use again "then" if the asynchronous chain have to continue or "done" if it is at the end. Here it is:

   1: this.showDialogAsync('do you confirm?')
   2:     .then(
   3:         function (success)
   4:         {
   5:             if (success)
   6:               console.log(a);
   7:         })
   8:     .then(/* continue here the chain */);
   9:  
  10: // or...
  11:  
  12: this.showDialogAsync('do you confirm?')
  13:     .done(
  14:         function (success)
  15:         {
  16:             if (success)
  17:                 console.log(a);
  18:         });

The difference between then and done are subtle. First of all, "done" returns "undefined" so it ends a chain so none can attach other operations. On the other side, when an exception is raised inside an asynchronous operation, "done" raises the exception but "then" swallow it; using "then" the exception simply disapper and this is not so good as you may think. To handle errors both "then" and "done" provide an optional function to be called in case of exception; this should be used at least on the "done" to ensure that nothing crash the application. Using done you can fallback to the WinJS.Application.onerror event to manage unhandled exceptions globally:

   1: WinJS.Application.onerror = function (ex)
   2: {
   3:     Debug.writeln(ex.message);
   4:     return true;
   5: };
   6:  
   7: this.showDialogAsync('do you confirm?')
   8:     .then(
   9:         function (success) { throw new Error('here is an error!'); })
  10:     .done(
  11:         function (success)  // <== success handler
  12:         {
  13:             if (success)
  14:                 console.log(a);
  15:         },
  16:         function (error)    // <== error handler
  17:         {
  18:             console.log(error.message);
  19:         });

One step forward: C#

If promises in Javascript are a beautiful and useful toolset, the ones that used C#, in its most recend version, knows that the language is almost one step beyond the promises, thanks to async-await keywords. As already said, the basis of the asynchronicity handling in C#, are very similar to the promises. In the following sample I show, it uses a couple of Task to download a page to a string. Due to .NET architecture this example can't work with MessageDialog as with Javascript because waiting on the UI thread, simply deadlock itself.

   1: private void Button_Click(object sender, RoutedEventArgs e)
   2: {
   3:     this.DownloadPage(
   4:         page =>
   5:         {
   6:             Debug.WriteLine(page);
   7:         });
   8: }
   9:  
  10: public void DownloadPage(Action<string> success)
  11: {
  12:     HttpClient client = new HttpClient();
  13:     
  14:     var downloadTask = client.GetAsync("http://xamlplayground.org");
  15:  
  16:     downloadTask.ContinueWith(response =>
  17:         {
  18:             var readTask = response.Result.Content.ReadAsStringAsync();
  19:  
  20:             readTask.ContinueWith(page =>
  21:                 {
  22:                     success(page.Result);
  23:                 });
  24:         });
  25:  
  26:     downloadTask.Wait();            
  27: }

In this example the Task object is used like a promise in Javascript. The ContinueWith method emulates the "then" or "done" method and I do a couple of "Wait" to start the task because in C# (differently from Javascript) creating a Task does not automatically start it. Written in this way the code is for sure hard to understand and it has also some disavantage from the corresponding Javascript. Fortunately the C# team introduced the async and await keywords that do all the work under the hoods on behalf of us. So the code becomes as follow:

   1: private async void Button_Click(object sender, RoutedEventArgs e)
   2: {
   3:     var page = await this.DownloadPage();
   4: }
   5:  
   6: public async Task<string> DownloadPage()
   7: {
   8:     HttpClient client = new HttpClient();
   9:     var response = await client.GetAsync("http://xamlplayground.org");
  10:     var page = await response.Content.ReadAsStringAsync();
  11:     return page;
  12: }

That's all folks! Please notice the "async" keyword that states the method should support the asynchronous call and the "await" used every time it calls an Async method. If you simply visually remove these keywords, the code becomes exactly the same as if it would run synchronously. And this is the awesomeness of the pattern: once you learn to use async-await you can simply return to write your code as if it was synchronous and simply the compiler does the dirty things for you. Magic!

The ECMA script 6.0 specs contains something similar to the async-await couple that is the "yield" operator. This will make Javascript to work the same as in C# but we have to wait some because, at the moment, it is only a proposition.

Multiple tasks

Both Javascript and C# supports also the join of multiple concurrent asynchronous operation. Let say you have to download a series of files, and you need to make it together with a single call. here is the Javascript sample:

   1: var promises = [];
   2:  
   3: promises.push(this.downloadFile('http://xamlplayground.org'));
   4: promises.push(this.downloadFile('http://blog.boschin.it'));
   5: promises.push(this.downloadFile('http://silverlightshow.net'));
   6:  
   7: WinJS.Promise.join(promises)
   8:     .done(function (result)
   9:     {
  10:         // handle all the results
  11:     });
  12:  
  13: WinJS.Promise.any(promises)
  14:     .done(function (result)
  15:     {
  16:         // handle the first
  17:     });

Here the "join" and "any" methods do the magic. They creates a single promise that is the sum of all the ones into the array. The "join" returns when all the promises has been fulfilled. Instead, the "any" returns when the first is completed. The same can be done in C#:

   1: Task<string>[] tasks = new Task<string>[]
   2: {   
   3:     this.DownloadPage("http://xamlplayground.org"),
   4:     this.DownloadPage("http://blog.boschin.it"),
   5:     this.DownloadPage("http://silverlightshow.net")
   6: };
   7:  
   8: var allResult = await Task.WhenAll(tasks);
   9: var anyResult = await Task.WhenAny(tasks);

Again, thanks to the async-await keywords the syntax is much more compact than the corresponding Javascript but the two languages are able to accomplish equally the same operations.

Async is better

There is not any doubt that asynchronous is better. When Silverlight firstly married this philosophy, people had an hard time to enter the pattern because they miss the right tools to make work easy. But, after having undestood the reasons, people goes on the right track simply forgetting the synchronous way that causes freezing and bad user experience. To me this has been a great step forward and now, with these awesome tools it is also easy like a breeze.


Subscribe

Comments

No comments

Add Comment

Login to comment:
  *      *       

From this series