Man, am I ever slammed. I'm in major crunch mode at the moment. Oh, well. This is the last of my posts on displaying the progress of a long-running process (LRP) by using ASP.NET AJAX stuff.
This final note has to do with canceling the LRP, specifically in the scenario where the LRP is running in a loop on the server and you're using AJAX to periodically check its status. The LRP was launched inside an UpdatePanel control, so it's running asynchronously. Inside UpdatePanel controls, starting a new async request "cancels" any previous request.
To "cancel" a request, you can also use the client-based PageRequestManager class, which handles the client end of async postbacks. This class lets you check the status of a request, and it includes an abort method that "cancels" the request. There's a nice example here.
I keep doing this annoying thing with quotation marks ("cancel") because you're not really canceling the request. What you're doing, as Eilon explained to me, is telling the PageRequestManager instance to ignore that request. The request finishes, the server sends the response, but we don't care any more. Ditto when you start a new async request -- the old is still live, but we're turning our attention to the new one.
So the LRP is still running. If you've got a heavy-duty LRP running, and if you're no longer interested in it, you can let it just run its course, but that's not going to scale. So you need to cancel it for real.
In my easy scenario, the LRP runs discrete steps in a loop, and on each iteration, it updates the status info. To add a real cancel to the process, therefore, you put some logic into the loop not only to update the status, but to check a flag to see if you're supposed to stop yourself. Since I was using a Profile property for the status info, I just added a second property named CancelLRP that works as a cancel flag. The loop adds this:For i As Integer = 0 To _totalRowCount - 1
If Profile("CancelLRP") = True Then
Profile("FWLinkcounters") = "canceled"
Profile.Save()
labelTime.Text = "Canceled " & DateTime.Now.ToString()
Exit For
End If
resultString &= (i + 1).ToString() & ". " & _
TestLink(i) & "
"
rowCounter += 1
If i = _totalRowCount - 2 Then
Profile("FWLinkcounters") = "done"
Else
percentDone = rowCounter / _totalRowCount
Profile("FWLinkcounters") = String.Format("{0} ({1}%)", _
CreateBar(percentDone, _totalRowCount, 20), _
(Math.Ceiling(percentDone * 100)).ToString())
End If
Profile.Save()
Next
I had to actually set this flag in client script, which was easy enough:function buttonCancelLRP_click()
{
Sys.Services.ProfileService.properties.CancelLRP = true;
var spanProgressDisplay = document.getElementById("spanProgressDisplay");
spanProgressDisplay.innerHTML += "<br/><br/>Canceled";
prm.abortPostBack(); // Tells the framework we're done.
window.clearTimeout(timerID);
return false; // Required to prevent normal postback
}
That's it.
Now that you've slogged your way through this, I note somewhat guiltily that all of this and plenty more has been documented by the brilliant Dino Esposito in a recent article in MSDN Magazine. That man is amazing. I don't feel quite as bad as I might, because AFAIK, the article appeared only after I'd started my project. (Talk about a long-running process, sheesh.)
In any event, have a look at his stuff, it's great, as always. And keep those LRPs running.
PS Here's the whole series in order.
Part 1
Part 2
Part 3
Part 4
Part 5