Channels ▼
RSS

Tools

Using Asynchronous Methods in ASP.NET 4.5 and in MVC 4


The following listing shows the code for the MathController class that provides two asynchronouns controller methods: TotalSummaryAsync and TotalSummaryParallelTasksAsync:

namespace Mvc4AsyncAwaitSample.Controllers
{
    using System;
    using System.Web.Mvc;
    using System.Threading;
    using System.Threading.Tasks;

    using Models.Math;

    public class MathController : Controller
    {
        public async Task<ActionResult> TotalSummaryAsync()
        {
            var detailsModel = new DetailsModel
            {
                SubTotal = await MathService.GetSubTotalAsync(),
                OtherCharges = await MathService.GetOtherChargesAsync()
            };

            return View("TotalSummary", detailsModel);
        }

        public async Task<ActionResult> TotalSummaryParallelTasksAsync()
        {
            var subTotalTask = MathService.GetSubTotalAsync();
            var otherChargesTask = MathService.GetOtherChargesAsync();

            await Task.WhenAll(subTotalTask, otherChargesTask);

            var detailsModel = new DetailsModel
            {
                SubTotal = subTotalTask.Result,
                OtherCharges = otherChargesTask.Result
            };

            return View("TotalSummary", detailsModel);
        }
    }
}

The MathController.TotalSummaryAsync method has the async modifier in its declaration, returns a Task<ActionResult> instead of an ActionResult, and uses the await keyword to execute both MathService.GetSubTotalAsync and MathService.GetOtherChargesAsync with an asynchronous execution. The code will wait for GetSubTotalAsync to return a value for the SubTotal property and then, it will execute the GetOtherChargesAsync method with an asynchronous execution to assign its result to the OtherCharges property. After both properties have their required values, the code will return the View (see Figure 6). As previously explained, the advantage of this approach is that the thread used to service the request is allowed to respond to other requests while the asynchronous method is waiting for the I/O operation in each call to WebClient.DownloadStringTaskAsync.


Figure 6. The TotalSummary view displaying the two results retrieved with an asynchronous execution.

This would be the declaration of a synchronous TotalSummary method:

public ActionResult TotalSummary()

Take a look at the difference with the declaration of the asynchronous TotalSummaryAsync method:

public async Task<ActionResult> TotalSummaryAsync()

The MathController.TotalSummaryParallelTasksAsync method has the async modifier in its declaration and returns a Task<ActionResult> instead of an ActionResult. However, this method takes a different approach than the previously explained TotalSummaryAsync. Instead of unwrapping the decimal value returned by both MathService.GetSubTotalAsync and MathService.GetOtherChargesAsync, the code calls both methods without using the await keyword, and therefore, they won't be launched at that time. Instead, the each method call will return a Task<decimal> instance. The local variables subTotalTask and otherChargesTask are Task<decimal> instances that will be scheduled and executed. Thus, the code waits for them to complete in parallel whenever possible with the following line that uses the await keyword:

await Task.WhenAll(subTotalTask, otherChargesTask);

The code won't continue until both subTotalTask and otherChargesTask complete their execution. If completion was successful, the Result property for both Task<decimal> instances will have the value returned by the asynchronous methods. The code assigns the values for the Result properties to the appropriate properties of the new DetailsModel instance, and then displays the View. Of course, in order to keep things simple, there is no exception handling. However, that would be necessary in a real-life usage.

The MathController.TotalSummaryParallelTasksAsync method provides a simple example on how to take advantage of the async and await modifiers in order to launch I/O bound tasks in parallel to increase responsiveness.

Now that you can see tasks in action again, you might start thinking about timeouts and cancellation tokens. As you might guess, there is support for them. The following lines show a simple example of a new TotalSummaryParallelTasksWithTimeoutAsync asynchronous method declaration with some attributes that define the desired behavior when an asynchronous method call times out:

  • AsyncTimeout established the timeout in milliseconds (300 milliseconds).
  • HandleError defines that whenever an exception of the type TimeoutException should display the ServiceTimedoutError view
[AsyncTimeout(300)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "ServiceTimedoutError")]
public async Task<ActionResult> TotalSummaryParallelTasksWithTimeoutAsync(CancellationToken cancellationToken)

You don't need to specify a CancellationToken instance when you call TotalSummaryParallelTasksWithTimeoutAsync. The instance is automatically generated by the ASP.NET MVC 4 engine. You can use the cancellationToken parameter to pass it as a parameter to each of your asynchronous method calls that support cancellation tokens. Of course, you will need to consider that in each of your asynchronous methods. However, if you worked with tasks before, you will know how to handle them.

Conclusion

In this second article, I've provided a few examples of asynchronous methods in both a WPF application and in ASP.NET MVC 4. You can start thinking about the advantages of using asynchronous methods in your applications. Asynchronous methods are an essential part of the new Windows 8 apps User experience, and therefore, it is very important to consider them no matter the kind of application you're developing. In the next article, I'll provide a detailed overview of the most useful new features and improvements included in WPF over .NET Framework 4.5, with examples of real-life usages.


Gaston Hillar is a long-time Windows programmer and a frequent contributor to Dr. Dobb's.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video