In the previous part of this 3-part blog post I talked about Task Parallel Library,

I used a simple example of a Stock quote request sample application.

Now in this post I want to transition into looking at asynchronous methods and how that was changed in .NET 4.5. I’m going to try to demonstrate how using the keywords async and await can make our code being a lot cleaner and a lot more understandable. I’ll take the previous example from previous post.

private async void GetQuotesBtn_Click (object sender, RoutedEventArgs e) {
  getQuotesBtn.IsEnabled = false;
  await Task.Run (() => Thread.Sleep (3000));
  getQuotesBtn.IsEnabled = true;
  statusMessageLabel.Content = "Quotes Received Successfully";

  //Previous TPL code
  //getQuotesBtn.IsEnabled = false;
  //var task = Task.Run(() =>
  //{
  //    Thread.Sleep(3000);
  //});

  //task.ContinueWith((t) =>
  //{
  //    Dispatcher.Invoke(() =>
  //    {
  //        getQuotesBtn.IsEnabled = true;
  //        statusMessageLabel.Content = "Quotes Received Successfully";
  //    });
  //});
}

Notice the async keyword in the method signature.

The async keyword does nothing on its own. It effectively just enables the new asynchronous features and basically tells the compiler that this method has the capability of running asynchronous code. This keyword must be present before you can use the other new keyword, await.

The easiest way to think about the await keyword is that it provides a similar service to a task’s ContinueWith method as was discussed in previous post.

As you can see in the code I’m adding the await keyword right in front of a task which means that I’m scheduling a continuation for that task and everything below that will be executed as a continuation when that asynchronous operations is completed, so in the example the UI will be updated after the 3 seconds by running these 2 lines of code.

getQuotesBtn.IsEnabled = true;
statusMessageLabel.Content = "Quotes Received Successfully";

One important thing to notice here is that when using the await keyword the continuation is executed on the calling context which in this case is the UI Thread.

After applying some refactoring to the previous code I come out with this:

private async void GetQuotesBtn_Click (object sender, RoutedEventArgs e) {
  getQuotesBtn.IsEnabled = false;
  var result = await Task<string> .Run (() => {
    Thread.Sleep (3000);
    return "Quotes Received Successfully";
  });

  getQuotesBtn.IsEnabled = true;
  statusMessageLabel.Content = result;

}

Here I’m just returning “Quotes Received Successfully”; from the asynchronous operation, then

Whenever the await keyboard is used that’s going to wait for that operation to complete, grab and return the result.

Next here I’m just extracting the logic from click handler to a new method, simulating just a more realistically scenario.

private async void GetQuotesBtn_Click (object sender, RoutedEventArgs e) {
  GetQuotesAsync ();
}

private async void GetQuotesAsync () {
  getQuotesBtn.IsEnabled = false;
  var result = await Task<string> .Run (() => {
    Thread.Sleep (3000);
    return "Quotes Received Successfully";
  });

  getQuotesBtn.IsEnabled = true;
  statusMessageLabel.Content = result;
}

After this change the application is still working but now we don’t have anything here to help the compiler track this asynchronous operation. Let say we want to do something else after GetQuotesAsync() call, we right now can’t do that.

Well it turns out that the fix for this is just as simple as adding Task as the return type in our GetQuotesAsync method.

private async void GetQuotesBtn_Click (object sender, RoutedEventArgs e) {
  try {
    await GetQuotesAsync ();
  } catch (Exception exception) {
    statusMessageLabel.Content = "Getting Quotes Failed!!";
  }
}

private async Task GetQuotesAsync () {
  getQuotesBtn.IsEnabled = false;
  var result = await Task<string> .Run (() => {
    Thread.Sleep (3000);
    return "Quotes Received Successfully";
  });

  getQuotesBtn.IsEnabled = true;
  statusMessageLabel.Content = result;
}

Now we can apply the last refactoring and make the necessary UI changes in the caller.

private async void GetQuotesBtn_Click (object sender, RoutedEventArgs e) {
  try {
    getQuotesBtn.IsEnabled = false;
    var result = await GetQuotesAsync ();
    getQuotesBtn.IsEnabled = true;
    statusMessageLabel.Content = result;
  } catch (Exception exception) {
    statusMessageLabel.Content = "Getting Quotes Failed!!";
  }
}
private async Task<string> GetQuotesAsync () {
  try {
    return await Task<string> .Run (() => {
      Thread.Sleep (3000);
      return "Quotes Received Successfully";
    });
  } catch (Exception e) {
    return "Getting Quotes Failed!!";
  }
}

With this in place we have made our code much simpler and easier to read.

In the next Post I’ll talk about Async and Await ASP.NET

[vc_custom_heading text=”” link=”url:https%3A%2F%2Fgithub.com%2Fcdcalderon%2FAsyncAwaitDemoCode|title:Sample%20Code|target:%20_blank|”]