Call to PageAsyncTask Times Out Every Time


P

Paul

Hi,

I've been struggling with this today, I'm developing a DotNet2.0 website in C# that needs to call a long running data query. Obviously this is a good candidate for an Asynchronous call, so the page can carry on rendering whilst the call is taking place and also returning the ASP.NET worker thread to service another page request (for scalability). I have developed a very basic asynchronous object (for testing, that reproduces the same error as my long running query object). Code for the object is as follows:

==========================================
using System;
using System.Threading;

public class TestAsyncClass
{
public TestAsyncClass(){}

private delegate string InvokeTest();
private InvokeTest deleg;

public string Test()
{
Thread.Sleep(1000);
return "Hello, World!";
}

public IAsyncResult BeginTest()
{
deleg = new InvokeTest(Test);
return deleg.BeginInvoke(null, null);
}

public string EndTest( IAsyncResult asyncResult)
{
return deleg.EndInvoke(asyncResult);
}
}
==========================================


The above class can be called from a very basic ASP.NET page as follows:

==========================================
TestAsyncClass testAsyncClass = new TestAsyncClass();

protected void Page_Load(object sender, EventArgs e)
{
IAsyncResult iasyncResult = testAsyncClass.BeginTest();
while (!iasyncResult.IsCompleted)
{
Response.Write("<Br>...Waiting");
Thread.Sleep(500);
}
Response.Write("<Br>" + testAsyncClass.EndTest(iasyncResult));
}
==========================================

As I'd expect, it produces the following:

...Waiting
...Waiting
Hello, World!


However, I don't think the above is really doing what I want, as it ties up the page waiting for it to finish. If I attempt to call the async class using the code below, which I believe will free up the page to do other stuff, then the request always times out (which is my problem).

==========================================
TestAsyncClass testAsyncClass = new TestAsyncClass();

protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask task = new PageAsyncTask(BeginTest, EndTest, TestTimedOut, null, true);
Page.AsyncTimeout = new TimeSpan(0, 0, 5);
Page.RegisterAsyncTask(task);
}

public IAsyncResult BeginTest(object sender, EventArgs e, AsyncCallback callBack, object extraData)
{
Response.Write("<Br><Br>Calling Begin Test");
return testAsyncClass.BeginTest();
}

public void EndTest(IAsyncResult result)
{
Response.Write("<Br>...Successful: ");
Response.Write( testAsyncClass.EndTest( result));
}

public void TestTimedOut(IAsyncResult result)
{
Response.Write("<Br>...Timed Out");
Response.End();
}
==========================================

Produces the following:

Calling Begin Test
...Timed Out

I don't think I'm passing the IAsyncResult around properly or I'm confusing the two Asynchronous calls. I'm pretty sure that the issue is in my object "TestAsyncClass()" as my the above web page code using "PageAsyncTask" is pretty much ripping off any example call to "SqlCommand.BeginExecuteReader()" and "SqlCommand.EndExecuteReader()". Can anyone throw any light on the problem / tell me the error of my ways. Note: the only change I made to the web page, other than "Page_Load()" is to add Async="true" to the @Page declaration.

Thanks in advance,

- Paul.
 
Ad

Advertisements

G

Guest

Paul,
I suspect the issue here is more one of user misinformation than anything
wrong with your code. ASP.NET Web pages don't behave like a Windows Form with
an asynchronous method kicked off. The Page lifecycle is basically halted
until the callback returns. So you should not expect some magical page
rendering and UI visible with your async task happily humming off in the
background somehow.

If you look up Fritz Onion's blog, he has written quite a bit about this and
it should help.
Peter

--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com
 
P

Paul

Thanks for the response Peter, I had found Fritz's blog on these issues when
googling for possible solutions. I've tried both methods documented on his
site, first is using "AddOnPreRenderCompleteAsync()" and the second is using
the "RegisterAsyncTask()" - neither appear to work for me in this instance.
All of the examples use the BeginXXX and EndXXX async. methods of either a
web service or a SQL command object (including Fritz's). In my case I
believe the issue lies in my "TestAsyncClass" object, which is trying to
imitate the functionality that the BeginXXX and EndXXX methods in the async.
web service SQL commands implemenent. As I understand it, from the example
on Fritz's site using "RegisterAsyncTask()" (see
http://pluralsight.com/blogs/fritz/archive/2005/02/14/5861.aspx)

1. ASP Page creates amd registers a Async Task via the RegisterAsyncTask(),
these include a BeginXXX, EndXXX and TimeOutXXX events
2. The ASP Page calls all the BeginXXX events registered in 1 above.
3. The BeginXXX event in the web page calls the BeginXXX event in the async
class (a web service in this case)
4. The ASP work thread can now work on finishing the rest of the page,
returning to the pool if the page reaches a point where it is no longer
required before the Async call has returned.
5. The existing ASP work thread (or a new one if existing one was returned
to the pool in step above) starts up to service the EndXXX event when it
fires. This is where my knowledge is a little fuzzy. I guess the "EndXXX"
event fires in the asnyc class, which somehow calls / fires the EndXXX event
in the web page. In my code, only the TimeOutXXX event in the web page
fires, which would appear to indicate that the EndXXX events in my async
class and web page are not linked / working together.

Hopefully that helps to explain my issue a little futher and / or my
misunderstanding of the process as a whole. Problem is I just can't see how
the examples would work if my understanding of the process, whilst flaky, is
incorrect.

thanks,

- Paul.
 
P

Paul

I tracked down the issue late last night, which was in my TestAsyncClass.
The call to the BeginTest() method was missing the two parameters
AsyncCallback and the object for extradata. The first of these fields
joins the callback function in the web page with the call back function in
my asynchronous class.

//public IAsyncResult BeginTest()
public IAsyncResult BeginTest(AsyncCallback callBack, object extraData)
{
deleg = new InvokeTest(Test);
//return deleg.BeginInvoke(null, null);
return deleg.BeginInvoke(callBack, extraData);
}

public IAsyncResult BeginTest(object sender, EventArgs e, AsyncCallback
callBack, object extraData)
{
Response.Write("<Br><Br>Calling Begin Test");

// return testAsyncClass.BeginTest();
return testAsyncClass.BeginTest(callBack, extraData);
}
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top