Wednesday, March 28, 2012

ASP.NET Ajax Progress Bar Revisited

I'm trying to create a Progress Bar that keeps track of a long running server-side process. I'm attempting to do this by having a primary ajax request start the server-side process, then having another polling function occassionally call back to the server via ajax to return the status if the server-side process started with the first ajax call. The problem is that the second ajax call doesn't return until the first one is completed.

Consider the following client-side code:

PageMethods.Execute(ExecuteCallback);

intervalId = window.setInterval(ExecuteStatus, 1000);
var done = false;

function ExecuteStatus()
{
PageMethods.ExecuteStatus(ExecuteStatusCallback);
}

function ExecuteStatusCallback( status )
{
<update progress bar>
if( !done )
window.setInterval( ExecuteStatus, 1000 );
}

function ExecuteCallback()
{
done = true;
}

PageMethods.Execute() is a server side process that can take a considerable amount of time. As it executes, it is setting a Session variable which indicates the status and completion percent of the process.

PageMethods.GetStatus() is a simple server side function which reads the aformentioned Session variable, and returns the status to the client.

The problem is that PageMethods.GetStatus() doesn't return until PageMethods.Execute() has completed and called back to the client.

Any ideas how to make this work?

Thanks much,

- Stew

I think you mean setTimeout instead of setInterval. Here's a working example. I hope this helps!

<%@. Page Language="C#" %><%@. Import Namespace="System.Web.Services" %><%@. Import Namespace="System.Threading" %><script runat="server"> [WebMethod] public static void Execute() { Thread.Sleep(5000); } [WebMethod] public static string ExecuteStatus() { return "."; }</script><!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>Untitled Page</title></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="sm" runat="server" /> <input type="button" value="Execute" onclick="DoExecute(); return false;" /> <span id="status">Ready.</span> </form></body><script type="text/javascript"> var done = false; function ExecuteStatus() { PageMethods.ExecuteStatus(function (result) { if (done) { $get('status').innerHTML = "Done!"; } else { $get('status').innerHTML += result; window.setTimeout(ExecuteStatus, 1000); } }); } function DoExecute() { done = false; PageMethods.Execute(function () { done = true; }); $get('status').innerHTML = 'Executing'; window.setTimeout(ExecuteStatus, 1000); }</script></html>

Steve, thanks for the response. Yes I did use setTimeout; I made a mistake when I typed the message above. I'm not sure why your test would work and not mine, but I'll take a look when I get home on Monday.

Thanks again

- Stew


Steve,

Try setting a session variable in your test before executing the test. This is what appears to be causing the problem.

- Stew

No comments:

Post a Comment