Jesper Jensen
Jesper Jensen

Reputation: 905

More than one await in HttpTaskAsyncHandler

HttpTaskAsyncHandler is a nice base-class for making async http-handlers in ASP.NET 4.5 I wonder how the runtime handles more than one await statement in ProcessRequestAsync.

public class CallbackHandler : HttpTaskAsyncHandler
{
    public override async Task ProcessRequestAsync(HttpContext context)
    {
        int value1 = await Task.Factory.StartNew(() => 1);
        int value2 = await Task.Factory.StartNew(() => 2);
        int value3 = await Task.Factory.StartNew(() => 3);

        context.Response.Write(value1 + value2 + value3);
    }

    public override bool IsReusable
    {
        get { return true; }
    }
}

Is the IIS thread being put on hold 3 times? How do i eventually test/see for this? Is it better to wrap the 3 awaits up in an asyn method?

Edit: I am concerned that this code will take a IIS-workerthread 4 times to handle this request. If i wrap it up in an async method - will it performe better?

Figure from MSDN mag article by Jeff Prosise

MSDN article

This is a diagram explaining the difference between sync and asyn page processing in ASP.NET. I am afraid that my example will result in 3 threads being started from the main worker thread (pink boxes on diagram) and thereby adding overhead.

IIS -> task1 TP -> IIS -> task2 TP -> IIS -> task3 TP -> IIS

(Task switching to the main IIS WT 4 times)

Or is the compiler so smart that it just passes continuation on from one task to the next, and returning to the main thread after the 3 tasks are done.

IIS -> task1 TP -> task2 TP -> task3 TP -> IIS

(Task switching to the main IIS WT 1 time)

Upvotes: 1

Views: 595

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 457057

It handles it just fine.

In IIS, you have a "request context" provided to your async handler, and your async methods by default will resume in that context. Whenever you await an incomplete task, the thread is returned to the thread pool (it is not blocked), and when that task completes, a thread pool thread is used to continue that async method after entering that request context.

So, no threads are "held", but the request itself is. Putting multiple awaits in another async method won't make a difference, but it would make a difference to start multiple Tasks and then wait for them all to complete, e.g., await Task.WhenAll(task1, task2, task3); (assuming that they are all independent, of course).

I don't know of a good way to verify this behavior.

Upvotes: 1

Related Questions