Async='true' take 2

Onion Blog

Syndication

Jon Flanders pointed out that the async flag I mentioned in my last blog entry of the Page class in ASP.NET 2.0 does in fact alter the generated code, and is not just a 'placebo' as I indicated. I thought it was worth a follow-up post describing exactly what it does in the current release bits.

If you mark a page as async, the generated Page-derived class is altered in the following ways:

  1. It implements IHttpAsyncHandler
  2. It sets the AsyncMode property to true in the constructor
  3. It implements IHttpAsyncHandler.BeginRequest/EndRequest by forwarding the calls to AsyncPageBeginProcessRequest/AsyncPageEndProcessRequest

 public virtual System.IAsyncResult BeginProcessRequest(HttpContext context,
                                                 AsyncCallback cb, object data) {
       return this.AsyncPageBeginProcessRequest(context, cb, data);
  }


public virtual void EndProcessRequest(System.IAsyncResult ar) {
      this.AsyncPageEndProcessRequest(ar);
}

What's interesting, is that the infrastructure is all in place to process this page on a different thread from the request thread, but it never actually creates a second thread to do the work on. Instead the async handler methods are invoked synchronously from the request thread. We'll have to wait and see how this turns out in the final release.


Posted Aug 16 2004, 02:10 PM by fritz-onion
Filed under:

Comments

Ian Griffiths wrote re: Async='true' take 2
on 08-17-2004 3:13 AM
I've not looked into ASP.NET 2 much yet so I might be completely wrong here... But is it possible that they might be looking to support the ability to do some async work in your codebehind before it goes on to generate the page?

On a few pages I've ended up with .aspx pages which have a certain amount of preprocessing work that could have been done asynchronously without necessarily tieing up any threads at all. E.g. if you're sending some message over a socket and must wait for a response, before you're ready to generate the page, then there's no need to tie up threads in the first phase. You could just to a BeginSend and BeginReceive on the socket, and use callback functions to handle the completion.

If you're writing your handler entirely from scratch, you could then use this to make your handler completely async - once the results are back in, generate the page content and complete the request. But there's no straightforward way of doing this today, as far as I know.

So what I'm thinking is some kind of approach where ASP.NET calls your AsyncBeginPageProcessRequest, and in here you fire off a bunch of intrinsically async (non-thread-consuming) operations. When the completion functions call you back, you then complete the request (i.e. your code calls the AsyncCallback that ASP.NET supplied you with) and ASP.NET will then carry on with the normal processing of the page.

This would avoid the common situation today of having a load of threads from the thread pool tied up in the early stages of .aspx handling - the part where you collect the data you require to populate the page.
Fritz Onion wrote re: Async='true' take 2
on 08-17-2004 4:09 AM
Interesting idea, Ian, but I'm pretty sure this is just a default implementation of the IHttpAsyncHandler interface where AsyncBeginPageProcessRequest is a helper function to implement the interface. I presume they will just spawn off a new thread (or draw a new one from a pool) in the final implementation of BeginProcessRequest to immediately release the request thread and do work on a separate pool.
BTW - comments are a nice feature in a blog, don't you think? :) :)
Fritz Onion wrote re: Async='true' take 2
on 08-17-2004 8:15 AM
I had a chat with Ian on IM, and he clarified his thinking. Because the BeginProcessRequest method was marked as 'virtual' he thought it might be possible to override it in a derived class, perform asyncIO work and then chain to the base class when you were ready. This would be a nice way of leveraging the async implementation, but since the virtual method is defined in the generated page-derived class, you can't derive from it! In 2.0 you will typically be using 'compilewith' which uses partial classes, and of course you cannot override a virtual method in the same class. Even if you resort to the 'classic' code-behind model, the generated class derives from you - not the other way around, so there is no way of using the 'virtualness' of the method in this case (in fact, one has to question why it is marked virtual at all).
Fritz Onion wrote re: Async='true' take 2
on 08-17-2004 8:47 AM
Just one more update, in case anyone is actually reading this :) Ian found an example in the docs (look at the help for BeginEventHandler delegate) that shows an intended usage of async='true' combined with a call to AddOnPreRenderCompleteAsync that looks like a nice solution to performing non-cpu bound work in a web page without tying up a request thread. I'll try this out in my test environment and post one more blog entry on the results. Perhaps this is the intended usage of the async attribute, and if so, it looks promising!
Mike Taulty's Weblog wrote Fritz Onion on Asynchronous ASPX pages in VS 2005
on 08-17-2004 3:21 PM
Onion Blog wrote Async Pages in ASP.NET 2.0 - some results
on 10-19-2004 12:46 PM
Some Assembly Required wrote Async Pages, Async Tasks, and AsyncTimeout
on 11-05-2005 8:35 AM
Magnus Salgo wrote re: Async='true' take 2
on 10-16-2006 12:59 AM
See MSDN http://msdn.microsoft.com/msdnmag/issues/06/07/ExtremeASPNET/default.aspx

Add a Comment

(required)  
(optional)
(required)  
Remember Me?