Bhushan Shah
Bhushan Shah

Reputation: 1038

Asynchronous MVC controller action method execution not waiting at 'await'

I am using MVC 4 along with .NET 4.5. I wish to build an asynchronous controller leveraging the new TAP (async await). I have inherited this controller from Controller and not AsyncContoller, since I am using task-based asynchronicity, not event-based asynchronicity.

I have two action methods - one to perform an operation synchronously, and another to perform the same operation asynchronously. I also have two submit buttons in the form in my View, one for each action method.

Here is the code for both the methods:

Synchronous:

[HttpPost]
public ActionResult IndexSync(FormCollection formValues)
{
        int Min = Int32.Parse(formValues["txtMin"]);
        int Count = Int32.Parse(formValues["txtCount"]);
        string Primes;
        DateTime started = DateTime.Now;
        using (BackendServiceReference.ServiceClient service = new ServiceClient())
        {
            Primes = service.GetPrimesServiceMethod(Min, Count);
        }
        DateTime ended = DateTime.Now;
        TimeSpan serviceTime = ended - started;
        ViewBag.ServiceTime = serviceTime;
        ViewBag.Primes = Primes;

        return View("Index");
}

Asynchronous:

[HttpPost]
public async Task<ActionResult> IndexAsync(FormCollection formValues)
{
        int Min = Int32.Parse(formValues["txtMin"]);
        int Count = Int32.Parse(formValues["txtCount"]);
        string Primes;
        Task<string> PrimesTask;
        DateTime started = DateTime.Now;
        using (BackendServiceReference.ServiceClient service = new ServiceClient())
        {
            PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
        }
        DateTime ended = DateTime.Now;
        TimeSpan serviceTime = ended - started;
        ViewBag.ServiceTime = serviceTime;
        Primes = await PrimesTask;
        ViewBag.Primes = Primes;

        return View("Index");
}

In the async method, I expect DateTime ended = DateTime.Now to execute immediately after the service method is called, while the time-consuming service method executes asynchronously in the background.

However, this does not happen, and the execution 'waits' when the service method is called, instead of waiting where Primes = await PrimesTask happens.

Is there anything I have missed?

A nudge in the right direction would be appreciated.

Upvotes: 3

Views: 2947

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 457302

I suspect that it is actually blocking in ServiceClient.Dispose.

To resolve this, extend the using block to include your await:

using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
    PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
    DateTime ended = DateTime.Now;
    TimeSpan serviceTime = ended - started;
    ViewBag.ServiceTime = serviceTime;
    Primes = await PrimesTask;
}
ViewBag.Primes = Primes;

Upvotes: 5

Related Questions