Calling ConfigureAwait from an ASP.NET MVC Action

Go To StackoverFlow.com

15

I was working on a presentation and thought the following should fail since the ActionResult isn't being returned on the right context. I've load tested it with VS and got no errors. I've debugged it and know that it is switching threads. So it seems like it is legit code.

Does ASP.NET not care what context or thread it is on like a client app? If so, what purpose does the AspNetSynchronizationContext provide? I don't feel right putting a ConfigureAwait in the action itself. Something seems wrong about it. Can anyone explain?

    public async Task<ActionResult> AsyncWithBackendTest()
    {
        var result = await BackendCall().ConfigureAwait(false);
        var server = HttpContext.Server;
        HttpContext.Cache["hello"] = "world";
        return Content(result);
    }
2012-04-04 03:52
by Dan Friedman
A correct answer should either say why doing this is totally OK or should give an example of what fails when you do try this. My gut tells me I shouldn't, but I would like to have facts to back me up - Dan Friedman 2012-04-05 02:55


6

ASP.NET doesn't have the 'UI thread' need that many clients apps do (due to the UI framework below it). That context isn't about thread affinity, but for tracking the page progress (and other things, like carrying around the security context for the request)

Stephen Toub mentions this in an MSDN article:

Windows Forms isn't the only environment that provides a SynchronizationContext-derived class. ASP.NET also provides one, AspNetSynchronizationContext, though it's not public and is not meant for external consumption. Rather, it is used under the covers by ASP.NET to facilitate the asynchronous pages functionality in ASP.NET 2.0 (for more information, see msdn.microsoft.com/msdnmag/issues/05/10/WickedCode). This implementation allows ASP.NET to prevent page processing completion until all outstanding asynchronous invocations have been completed.

A little more detail about the synchronization context is given in Stephen Cleary's article from last year.

Figure 4 in particular shows that it doesn't have the 'specific thread' behavior of WinForms/WPF, but the whole thing is a great read.

If multiple operations complete at once for the same application, AspNetSynchronizationContext will ensure that they execute one at a time. They may execute on any thread, but that thread will have the identity and culture of the original page.

2012-04-04 06:12
by James Manning
In event-based async, handling outstanding asynchronous invocations apply, but it doesn't seem to apply in Task-based async, since there wouldn't be any outstanding invocations by the end of the Action. Also, through debugging, I see that the user's form identity and their languages (security & culture) are still intact after the ConfigureAwait. So I'm reading reasons for the SyncContext, but nothing seems broken. What can I do to prove that ConfigureAwait should't be used here - Dan Friedman 2012-04-04 13:00


4

In your code, HttpContext is a member of your AsyncController base class. It is not the current context for the executing thread.

Also, in your case, HttpContext is still valid, since the request has not yet completed.

I'm unable to test this at the moment, but I would expect it to fail if you used System.Web.HttpContext.Current instead of HttpContext.

P.S. Security is always propagated, regardless of ConfigureAwait - this makes sense if you think about it. I'm not sure about culture, but I wouldn't be surprised if it was always propagated too.

2012-04-04 13:46
by Stephen Cleary
Yep, my variables will always be valid cause they just get wrapped up into the stack. But even System.Web.HttpContext.Current still has valid and correct data - Dan Friedman 2012-04-05 02:51
Is BackendCall returning synchronously - Stephen Cleary 2012-04-06 14:43
Nope. Besides a logical check, I've debugged it and watched it switch threads - Dan Friedman 2012-04-07 01:42
Ads