News

September 2006 Entries

Async web page execution using PageAsyncTask


 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); } }

posted @ Monday, September 11, 2006 9:12 PM | Feedback (2) |