Its seems most of my development these days involves some form of modular parts assembled at runtime in Windows SmartClient apps, or at Page Load time in customizable web part portal applications. In web portal apps, that are built out of independent web parts, page performance can degrade linearly with the number of parts included on any one page. Generally, if each of these parts is treated as a true module or smart web part then they are usually each responsible for getting their own data. Because of this, I find myself doing a lot more asynchronous work during page processing so that all the parts can come together in parallel within a reasonable amount of time. The trick is to not tie up the main worker thread as it waits for your async parts to finish, so that it can go back and handle other page requests. Asp.Net 2.0 enables this process with the Async=True page attribute. However, there is a little additional magic that happens behind the scenes when using web services via proxies that were created with Asp.Net 2.0 web references.
When adding a web service reference to .Net 2.0 Asp.Net app, you may notice that for each web method there is a "async" method also created in the reference file. Since .Net 1, we have gotten both the standard synchronous method implementation, and also the corresponding Begin/End async methods (following the standard IAsyncResult pattern). However, in .Net 2.0, web references also create a third choice, which uses a delegate callback pattern. When this async method is used to populate a control in conjunction with a web page marked with the Async="True" Page directive, some interesting stuff happens. Behind the scenes, when the async version of the method is called on the web proxy, "InvokeAsync" of the proxy's SoapHttpClientProtocol base class is called, which in turn registers this call with .Net 2.0's AsyncOperationManager. If you have been using the Async=True page directive in Asp.Net 2, you are probably familiar with calling Page.RegisterAsyncTask to do some async work. For those not familiar with this, Async=True will allow a page to process up to pre-render, but then it will relinquish its main Asp.Net processing thread, until it's registered async tasks finish. The powerful thing about using the new async web methods, is that this call to RegisterAsyncTask is wired up implicitly for you. So, you mark a page with the Async=True attribute, call upon the asynchronous version of the web method, and the RegisterAsyncTask is wired up for you.
Fritz explains this awsome feature in detail in his June Extreme Asp.Net article.