When you run the application, if you click the Add total button, it won't block the UI. In fact, you can click on the button a dozen of times and the total values will start appearing later as the asynchronous calls finish their execution. You didn't need to think about either tasks or threads and you created a responsive UI. Of course, .NET is doing a lot of work under the hood.
Debugging asynchronous methods is simple because you can step-into and step-over just as you do with synchronous code. However, you won't have the full Call Stack details. For example, if you step into the GetSubTotalAsync method within GetCalculatedTotalAsync, if you continue the execution step-by-step and you stop after the asynchronous call to DownloadStringTaskAsync finished, you will see that the Call Stack changes and displays a row with the following label after the current method name [Resuming Async Method]. See Figures 2 and 3.

Figure 2. You have the full Call Stack details until you resume an asynchronous method call.
You can go on executing code step-by-step and you will return to the original methods that made asynchronous calls. Visual Studio doesn't display the original methods in the Call Stack window, but you can go on debugging as if you made synchronous calls.

Figure 3. The Call Stack window displays a [Resuming Async Method] label when you resume an asynchronous method call.
Exception handling in asynchronous methods
Exception handling in asynchronous methods works in the same way as in synchronous methods. The following lines show a new version of the GetSubTotalAsync method that throws an exception of type System.UriFormatException:
private static async Task<decimal> GetSubTotalAsync()
{
var downloadedString =
await new WebClient().DownloadStringTaskAsync(new Uri(
"What's new in .NET Framework 4.5 @ www.drdobbs.com"));
return (decimal)downloadedString[0];
}
The following lines show a new version of the MathService.GetCalculatedTotalAsync method that catch any exception that might occur in any of the asynchronous method calls. The code just returns -1 if an exception occurred and writes the exception details to the trace listeners. If you run the code, you can check that an exception that you can catch any exception thrown by any asynchronous methods without having to worry about the tasks and threads used to support the methods' execution. See Figure 4.
public static async Task<decimal> GetCalculatedTotalAsync(decimal salesTaxPercentage)
{
try
{
var subTotal = await GetSubTotalAsync();
var otherCharges = await GetOtherChargesAsync();
var subTotalPlusOtherCharges = subTotal + otherCharges;
var salesTax = Math.Round(
subTotalPlusOtherCharges * salesTaxPercentage, 2,
MidpointRounding.AwayFromZero);
return subTotalPlusOtherCharges + salesTax;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
return -1;
}
}

Figure 4. An exception caught in the method that calls many chained asynchronous methods.



