Problems with Asynch Processing in ASP.Net

G

Glen Wolinsky

This is my first attempt as asynchronous processing. I have created a
small test app as proof of concept, but I am having one proglem. In
the example (code listed below), my callback routine has two problems:

1. It runs TWICE; and
2. While it seems to update the web page controls, the results never
show up on the page.

I am using delegates per a couple of examples I found on MSDN and
elsewhere.

What I'm trying to accomplish is to spawn an asynchronous routine from
the page. When the routine is complete and the callback routine
executes, it should update the screen to let the user know it's done.

Any help would be greatly appreciated. My code is listed below.

Sincerely,
Glen Wolinsky

--------------------------
Numbers 6:24-26
--------------------------
-------------------------------------------------------------------------------------------------------------

Imports System.Threading

Public Class AsynchTest1

Inherits System.Web.UI.Page

Protected WithEvents btnGo As System.Web.UI.WebControls.Button
Public Delegate Function TestDelegate() As String
Dim intTemp As Integer

------Page Load
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

End Sub

------Button to start process
Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnGo.Click
Session("StartProc") = Today.Now

Dim TestDlgt As TestDelegate = New TestDelegate(AddressOf
TestRoutine)

Dim ar As IAsyncResult = TestDlgt.BeginInvoke(New
AsyncCallback(AddressOf TestComplete), _
Nothing)

lblStatus.Text = "Procedure started..."

End Sub

-------Asynchronous Routine
Private Function TestRoutine() As String
Dim start As DateTime

SyncLock Session.SyncRoot
start = Session("StartProc")
End SyncLock

Do While (Date.Now.Ticks - start.Ticks) < 100000000
'Process this loop for a few seconds
Loop

Return "The asynchronous process is complete"
End Function


------Completion callback routine
Private Sub TestComplete(ByVal ar As IAsyncResult)
Dim ad As TestDelegate = CType(ar.AsyncState, TestDelegate)

lblStatus.Text = ad.EndInvoke(ar)
lblStatus.ForeColor = Color.Red

End Sub

End Class
 
B

bruce barker

your missing the concept of how page processing happens.


browser requests pages (or post on click) -->

server builds page
oninint
onload
onclick
onprerender
onrender
<-- page sent back

browser renders page

you are starting a async proc during onclick, but you have no delay (say at
prerender) on the page to wait for the async process to complete. so the
page html is sent back to the browser before it completes. it can change
class variables and controls, but will have no impact, because the response
has already been sent.

if you want the page to render, then be updated after the async is done, the
browser needs to poll for the results. have the async routine write its
results to session, then using the refresh meta tag, postback every couple
seconds to see if it has completed. a little javascript and a hidden frame
can be handy here.

-- bruce (sqlwork.com)
 
G

Glen

Michael,

Thanks for the reply. I looked at threading and got some samples
working well using session variables for status info.

However, after reading several articles on this type of thing, the
consensus seemed to be that asynch processing was better and more
scaleable than threading.

I need this feature for just a handful (2-5) users who do large searches
on our data warehouse. The search runs fine but the exporting of that
data to other systems or to an excel spreadsheet causes the browser to
time out.

I got one asynch test working, but I still had to use session variables
to check status.

Should I be using asynch to let asp.net manage the thread pool for me?
Anyone who can advise me on the pro's and con's of each would be greatly
appreciated.

Sincerely,
Glen Wolinsky
 
G

Glen

Bruce,

Thanks for your response. I have managed to get that exact scenario
working in both threading and asynch processing. My next question is
this: Which one is best to use? They both seem to do the same thing
except that asynch has a few extra "bells and whistles" and uses the
thread pool.

Thanks,
Glen Wolinsky
 
S

Steven Cheng[MSFT]

Hi Glen,


Thanks for posting in the community! My name is Steven, and I'll be
assisting you on this issue.
From your description, you'd like to implement a asynchronous processing to
register a call back method when page is being generated and loading so as
to use the call back method to update some certain server controls when a
certain longtime operation is completed. However you found it didn't work
as you expected when you run the test page, yes?
If there is anything I misunderstood, please feel free to let me know.

As for this problem, here is my suggestion on it:
The ASP.NET web application is one kind of the page based B/S mode
application. The application consist of two parts: the severside and the
client side. Generally, the client side user request a certain page on the
server, the then the server side use the Dynamical document tech such as
ASP.NET to create the page (which start the server page's life cycle , page
init , load .....). And all the serverside code all being executed during
the lifecyle, after the page is generated and ouput(render) to client side.
The page's server life cycle ended and there is no relation between the
client page and the memory page object on the serverside(in fact, it'll be
cleared in the server side memory). And in the next time the same page
requested, another page instance will be generated in serverside memory. In
other words, no persistant connection is remained between the client and
the server, this is also the characteristic of the HTTP based compute
mode-------stateless. That's quite different from the mode in Winform
application , in which all the object instance are all in memory during the
runtime and can be retrieve and maintain until the program end. So as for
your situation, the asynthronized call back method is registed in the
page's life cycle, at that time , the page and its sub object instances are
all avaliable on the serverside. However, when the certain task finished,
just when the callback method is called, the page may have already been
output to the client side, so it's unable to retrieve the page and modify
it's members. Also, even if you get the object, there is not relation with
the instance and the client side's page. Do you think so? For more info
about the ASP.NET page model, you may view the following reference in MSDN:
#The ASP.NET Page Object Model
http://msdn.microsoft.com/library/en-us/dnaspp/html/aspnet-pageobjectmodel.a
sp?frame=true

In addition, as for your requirement, I think we could use other means to
implement it in B/S mode application. For example, we could let the page be
send back to client and continue the operation on the serverside, and the
page in the client side constantly post back to server side to check
whether the operation is completed, if so, then do the later operations.
And here is some tech articles which focus on such asynchronous pattern in
web application:

#DESIGN PATTERNS: Asynchronous Wait State Pattern in ASP.NET
http://msdn.microsoft.com/msdnmag/issues/03/12/designpatterns/default.aspx
http://www.aspnetpro.com/NewsletterArticle/2003/08/asp200308bm_l/asp200308bm
_l.asp

Please check out to see whether they're helpful. In the meantime, if you
have any further questions, please feel free to post here.



Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
G

Glen

Steven,

Thanks for all of the information. You have confirmed everything I have
read and learned on this subject in the past 5 days. Now, I have
another question:

Scenario:

1. A user selects a long-running action (process).

2. I take the user to a "wait" page. The wait page actually spawns the
thread (on my own without using async processing) and keeps posting back
to monitor the process via session variables.

3. If I save a reference to the thread object in session, can I abort
the thread using code in my page?

What I'm trying to accomplish is that if the user exit's the page
(including closing the browser window) that the thread(process) will be
aborted.

Any thoughts, suggestions or other miscellaneous ideas? ;o)

Thanks,
Glen Wolinsky
 
S

Steven Cheng[MSFT]

Hi Glen,


Thanks for your response. As for the questions you mentioned in the reply,
here is my suggestions:
1. You'd like to run a work thread on the serverside and store the thread
object in session. And you'd like to retrieve back and do operations on it
(such as abort or stop). This is ok, you can first create the thread and
start it at begining. For example:
ThreadStart ts = new ThreadStart(DoWork);
Thread thd = new Thread(ts);
thd.Start();
Session["thread"] = thd;

Then, when in one of the page's post back event, you could retrieve the
thread object and suspend or abort it, for instance:
private void btnAbort_Click(object sender, System.EventArgs e)
{
try
{
Thread thd = (Thread)Session["thread"];
thd.Abort();
}
catch(Exception ex)
{
Response.Write("<br>" + ex.Message);
}
}

2. You'd like to abort such a serverside background thread when user exit
site or close browser window?
As for this problem, I think it is easy to accomplish in case user
explicitly exit the page(such as click a button), you can abort the thread
as I mentioned above. However, the difficulty is when the user just close
the browser,. As we know that if the browser is closed, no relation between
the client and server exist. , so we need to let the serverside know that
the user has left, and here is two general means to accomplish this:
1). use the client script to capture the page's "onunload" event and then
post back to certain page to do the cleanup operations. For example, in the
page set such unload handler
-------------------------
..............
<script language="javascript">
function CloseHandler()
{
if(window.closed)
{
window.open("CleanUp.aspx");
}
}
</script>
</HEAD>
<body onunload="CloseHandler()" >
...................

In the CleanUp.aspx we add the clean up operations such as abort the
thread or release other resources.
# this means has a problem: when you refresh the page(not close it), the
"unload" event will also be fired!

2). Use the "Session_End" event of the Global object on serverside. Since
when the Session is ended(user logout) or Timeout(user long time no visit
the application). The Session_End event will be fired, we can also do the
clean up operations in it.

Please check out the above suggestions. If you have any questions on them,
please feel free to let me know.



Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
G

Glen

Steven,

Thanks for all your time. You've been very helpful. One more question:

if I raise an event in a threaded process, can my "Wait.aspx" page
detect that event?

Thanks,
Glen
 
S

Steven Cheng[MSFT]

Hi Glen,


Thanks for your prompt response. As for the question in your reply:
---------------
if I raise an event in a threaded process, can my "Wait.aspx" page
detect that event?
---------------

here is my suggestions:
As I 've mentioned in the former reply. The certain threaded process is
running on the serverside. And the wait.aspx will be rendered out and send
to the clientside and the page's life cycle is only during the time it is
constructed and operated on the serverside(it's a very short time). So it
impossible to use the Dotnet event and callback mechanism to let a page be
sense of a serverside throwed event. I suggest that you use the below
approach:
1.Let the wait.aspx constantly post back to the server side to check a
certain Session object 's value. The value is just a flat to indicate
whether the certain threaded process has finished.

2.In the threaded process , when it has finished, set the certain Session
object 's value as the Finish state's value so that the next the wait page
post back , it can detect the change.

How do you think of the above means? If you still feel anything unclear on
it, please feel free to let me know.



Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
G

Glen

Steven,

Thanks. That scenario works great. I already have that working.
However, in one of your previous (and very informative) emails, you
brought up the following issue: I can't use the polling/postback method
and still use the method of trapping the OnUnload event to kill the
thread when a user closes the window manually.

Each of my polling refreshes fires the OnUnload event for the page and
kills the thread. I can't check the thread in the client since the
thread reference object is in the session on the server.

That's why I asked about raising and event. I figured it wouldn't work
for the exact reasons you stated, but I had to ask to be sure I wasn't
missing some trick.

Thanks for your help and of course any further suggestions you may have
would be greatly appreciated.

Sincerely,
Glen Wolinsky
 
S

Steven Cheng[MSFT]

Hi Glen,


Thanks for your followup. Yes, the problem "Each polling refreshes fires
the OnUnload event for the page" does be a headache and currently it seems
that there is not any further means or tricks to workaround it. Maybe the
means using "Timeout" such as Session's timeout event is a workaround. Any
way, thanks again for your confirm. If you have any thing else unclear,
please feel free to post here.


Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 

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

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top