At today's .NET user group meeting someone asked about doing async tasks in an ASP.NET page and not blocking. Here is one option in all it's g(l)ory:

The ASPX @page directive gains a AsyncTimeOut="3" which will make it wait up to 3 seconds for the async task to complete. Since the operation itself does not actually use an external resource, a fake out of the AsyncResult is done using a delegate and a BeginInvoke on it which yields the IAsyncResult that BeginEventHandler is expected to return and EndEventHandler requires. If the work was actually a http web request or something, it would have a BeginInvoke provided by the proxy.

The code in front:

==============================

 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Async="true" AsyncTimeOut="3" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Async processing</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Literal runat="server" ID="Output"></asp:Literal> </div> </form> </body> </html>

==============================

and the code behind:

==============================

 

using System; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class _Default : System.Web.UI.Page { protected delegate void DoTheWorkDelegate(); private DoTheWorkDelegate _doTheWorkDelegate; private TimeSpan _workTime = TimeSpan.FromSeconds(2); private string _report = ">"; public string Report { get { return _report; } set { _report += value + "... "; } } protected void Page_Load(object sender, EventArgs e) { if (! String.IsNullOrEmpty( Request.QueryString["t"])) { _workTime = TimeSpan.FromSeconds(double.Parse(Request.QueryString["t"])); } PageAsyncTask task = new PageAsyncTask( new BeginEventHandler(BeginAsyncOp), new EndEventHandler(EndAsyncOp), new EndEventHandler(TimedOutOp), null); RegisterAsyncTask(task); Report = "page load completed"; } protected override void Render(HtmlTextWriter wr) { Output.Text = Report; base.Render(wr); } IAsyncResult BeginAsyncOp(object sender, EventArgs e, AsyncCallback cb, object state) { this.Report = "Begin Async"; _doTheWorkDelegate = new DoTheWorkDelegate(doTheWork); return _doTheWorkDelegate.BeginInvoke(cb,state); } void EndAsyncOp(IAsyncResult ar) { Report = "End Async"; } void TimedOutOp(IAsyncResult ar) { Report = "Timed Out"; } void doTheWork() { System.Threading.Thread.Sleep(_workTime); } }