9

I'm using Visual Studio 2012 RC with .Net 4.5 and ASP MVC 4 RC. It hangs whenever I use async at all. The controller action method uses async but is not itself an async controller method.

There are no errors logged or exceptions thrown, but the browser shows "Waiting for www.myweb.local" forever.

// Simplest possible async
public class Waiter
{
    public async Task<int> GetValue()
    {
        await Task.Yield();
        return await Task.Factory.StartNew(() => 42);
    }
}

// simplest possible controller that uses the async
public class HomeController : Controller

    public ActionResult Index()
    {
        var waiter = new Waiter();
        var resultTask = waiter.GetValue();
        int result = resultTask.Result;

        // it never gets here 
        return View();
    }
}

I have done the things that are noted in this answer, and it still does not work. ie. The web.config contains

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>

And the magic words await Task.Yield(); are in the async method.

The .Net framework version is 4.5.50501. I have observed this behaviour on IIS Express and on IIS 6.0.

I tried applying the "July 2012 update" to VS2012, but that did not fix it.

This answer suggests that it may be because the task is already completed when I wait for it, however if that was the case, this should work and it does not:

public class Waiter
{
    public async Task<int> GetValue()
    {
        await Task.Yield();
        return await Task.Factory.StartNew(() => 
            {
                Thread.Sleep(1500);
                return 42;
            });
    }
}

A couple of people have suggested that ConfigureAwait(false) is needed, but this code does not work either:

    public async Task<int> GetValue()
    {
        var task = new Task<int>(() => 42);
        return await task.ConfigureAwait(false);
    }

The following does work with the razor view engine, but not with spark. Surely there should be a way to get the other scenario working as well? Can one not use the async Tasks inside synchronous code?

public class Waiter
{
    public async Task<int> GetValue()
    {
        return await Task.Factory.StartNew(() => 42);
    }
}

public class HomeController : Controller
{
    public async Task<ActionResult> IndexAsync()
    {
        await Task.Yield();
        var waiter = new Waiter();
        int result = await waiter.GetValue();

        return View();
    }
}

I know that is this isn't released software, but Microsoft's RCs are usually quite stable, so I'm surprised that it fails, and fails in an unhelpful way.

4
  • 2
    Sorry if I'm missing something, but why have the Index block via accessing the Result property instead of marking it async and using await there? If that's intentional, you might need to use ConfigureAwait(false) so the continuation doesn't schedule back on the same thread. Commented Jul 6, 2012 at 15:12
  • I'm testing porting an existing website to .Net 4.5. It uses the spark view engine. I wanted to get async working before I dealt with async controllers and whether spark could handle Task<ActionResult> or not (my initial impression was no). But regardless of whether I could do that or not, this scenario should work. Commented Jul 6, 2012 at 15:23
  • Why are you deriving from AsyncController? That's not necessary. See my async sample asp.net/mvc/tutorials/mvc-4/… Commented Jul 7, 2012 at 20:15
  • Thanks for that tip Rick, I have modified the code e.g. to fit. Commented Jul 7, 2012 at 23:32

2 Answers 2

11

You are causing a deadlock, just like this question.

James Manning's suggestion is correct, but you have to await the result of ConfigureAwait, like this:

public async Task<int> GetValue()
{
    var task = new Task<int> (() => 42);
    return await task.ConfigureAwait(false);
}

In general, mixing synchronous and asynchronous code is a Really Bad Idea unless you Really Know what you're doing. Making the controller action asynchronous would be much better.

Sign up to request clarification or add additional context in comments.

11 Comments

I agree - particularly as it's so easy now to make the controller methods asynchronous. Although I can see some (very very rare) cases where it might make sense to run some tasks in parallel within a synchronous handler. Always worth a read of this article before getting carried away with async controllers too: blog.stevensanderson.com/2010/01/25/…
Surely any c# program that uses the async keyword "mixes synchronous and asynchronous code"? Using an Async controller just means that the boundary is in the framework.
Regarding "it's so easy now to make the controller methods asynchronous" - not if you have a lot of existing views using the spark view engine.
@Anthony: What I mean by "mixing" is that there is an event controller for every app (UI apps have a message pump; ASP.NET apps have a request context). Extending async all the way to that event controller is the cleanest and easiest design. You don't want to "mix" in the sense of having a synchronous event handler call into an async layer.
I've never used spark, but if it's just a view engine, can't you make your controller methods async anyway?
|
1

I have had async working in the beta just fine. I've not tested it, but I'm guessing it's because your controller method is not async. Change it to this:

public async Task<ActionResult> IndexAsync()
{
    var waiter = new Waiter();
    int result = await waiter.GetValue();

    // it never gets here 
    return View();
}

3 Comments

If it's "because the controller method is not async" are you saying that using async tasks will never work in sync code? Otherwise, there should be a way to get this code working.
So GetValue() not completing then... I can't think of an obvious reason for that off the top of my head from what you've got and I'm on the train right now! I'll have a look later if no one's beaten me to it.
What happens if you access result (do something with it) after the await?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.