Threading in asp.net issue - Thread stops

  • Thread starter Thread starter Phil
  • Start date Start date
P

Phil

Hi,
I've a simple asp.net page with one button.
In the OnClick event, I want to create a thread that will perform a
long runninf task.
Here is a sample code

in the OnClick

Thread t = new Thread(new ThreadStart(this.Import));
t.Priority = ThreadPriority.Lowest;
t.Start();

Import Function

public void Import()
{
for (int i=0;i<100;i++)
{
Response.Write(i.ToString() + "<br>");
Thread.Sleep(100);
}
}

The issue is that my thread stop working really quickly. In this
example, the thread only display figures from 0 to 9... instead of
100...
Is there something special I should now about running threads in
asp.net?
Please advice.
Best regards
Philippe GRACA
 
Well the problem is that the ASP.NET thread continues and returns the response to the client, irrespective of your thread running.

What you are doing is A Really Bad Idea (tm) as you get a large number of requests you are going to kill your server with an uncapped number of threads (I've seen a similar setup dump 6000 threads on a server on a consulting gig I did a while back).

What are you trying to achieve by using a backgourd thread. ASP.NET is highly multithreaded already so it is rarely necessary to run bits of requests asynchronously.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Hi,
I've a simple asp.net page with one button.
In the OnClick event, I want to create a thread that will perform a
long runninf task.
 
Thx Richards
I was almost sure this was a bad idea ;)
What I'm trying to do is to propose to our users via a web interface
the capability to load 5 or 6 really huge XML files( > 100 Mb each) in
the App database (doing XSL tranform and then bulk inserts to sql
server). This should be done on demand almost immediatly since they do
not want to wait for any kind of batch or whatever. Once those files
are loaded, they can then perform comparisons and a lot of other
tasks.
On our end, the import job take around 13 minutes to complete but on
the user side, they are experiencing TCP problems (the connection is
lost but the job is indeed still running!!) . I though about this
threading approach essentially thinking of having a running thread
separate from the ASP.NET one so that users won't loose the HTTP
connection. I agree this is the bad way to solve the problem and maybe
an aynchronous Web service will do the trick. What do you think of
that? Any ideas, comment, code to share?
Regards and nice we :)
Philippe GRACA
 
Phil said:
I was almost sure this was a bad idea ;)
What I'm trying to do is to propose to our users via a web interface
the capability to load 5 or 6 really huge XML files( > 100 Mb each) in
the App database (doing XSL tranform and then bulk inserts to sql
server). This should be done on demand almost immediatly since they do
not want to wait for any kind of batch or whatever. Once those files
are loaded, they can then perform comparisons and a lot of other
tasks.
On our end, the import job take around 13 minutes to complete but on
the user side, they are experiencing TCP problems (the connection is
lost but the job is indeed still running!!) . I though about this
threading approach essentially thinking of having a running thread
separate from the ASP.NET one so that users won't loose the HTTP
connection. I agree this is the bad way to solve the problem and maybe
an aynchronous Web service will do the trick. What do you think of
that? Any ideas, comment, code to share?

It's reasonable to have a long-running thread doing the job, but don't
have a long-running request. Have a short request which sends a
response effectively saying "Check again in another 20 seconds" (using
an HTTP META-REFRESH or whatever) and keeps doing so until the long-
running job has finished, at which point it displays the results. If it
can display a meaningful estimate of the progress each time it
refreshes, that's even better.
 
Thx Jon,

Will you be so glad to send me our point me to some sample code please
because I am still not able to perform that?
Regards
Phil
 
Philippe Graca said:
Will you be so glad to send me our point me to some sample code please
because I am still not able to perform that?

I don't have any sample code, I'm afraid, but if you could explain
exactly where you're having trouble with it, I might be able to help.
Which bit isn't working?
 
I'm not saying that this is what Jon was suggesting but *don't* spawn a new thread on the request to process the files you'll potentially create an uncapped number of threads. Instead use a threadpool. However, don't use the CLR threadpool as that is what ASP.NET is using to service requests - instead use a custom threadpool. Luckily Mike Woodring has taken the pain out of this by creating one which you can get here.

http://www.bearcanyon.com/dotnet/#threadpool

Basically you're request queues a piece of work up to the threadpool and returns to the browser saying "processing ..." or something like that. The browser either auto refreshes by a meta refresh HTML tag or you get the user to check every now and then - the meta refresh is a better approach through. When the work is complete set a flag in session or something similar and the next time the browser resubmits stell them the work is complete, etc.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Thx Jon,

Will you be so glad to send me our point me to some sample code please
because I am still not able to perform that?
Regards
Phil
 
Well,
the issue is that when I create my thread, even if is not using
"Response" in its main method, its stops as soon as the page has
finished to render to the client. Any thoughts?
Phil
 
Phil said:
the issue is that when I create my thread, even if is not using
"Response" in its main method, its stops as soon as the page has
finished to render to the client. Any thoughts?

That sounds somewhat unlikely. Are you using anything else to do with
the request/response? Are any exceptions being thrown? (Either add an
unhandled exception handler to the app domain, or put the whole of the
thread's work in a big try/catch block.)
 
Threading is handled automatically in ASP.Net. You will have to rethink
on your technique of using another thread as it is going to cause lots
of performance problems for the web server and your app.

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- http://www.411asp.net/func/search?
qry=Ravichandran+J.V.&cob=aspnetpro
- http://www.southasianoutlook.com
- http://www.MSDNAA.Net
- http://www.csharphelp.com
- http://www.poetry.com/Publications/
display.asp?ID=P3966388&BN=999&PN=2
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
Ravichandran J.V. said:
Threading is handled automatically in ASP.Net. You will have to rethink
on your technique of using another thread as it is going to cause lots
of performance problems for the web server and your app.

Not necessarily. There are lots of scenarios where it makes sense to
use a long-running thread to do a large job of work, but make the
request/response time brief, just checking whether or not the job has
finished.

How else would you approach the situation where a job needs to be run
which will take longer than the response timeout?
 
Jon Skeet said:
Not necessarily. There are lots of scenarios where it makes sense to
use a long-running thread to do a large job of work, but make the
request/response time brief, just checking whether or not the job has
finished.

How else would you approach the situation where a job needs to be run
which will take longer than the response timeout?

Use EnterpriseServices to run long running tasks and take advantage of a
bunch of services offered by ES.

Willy.
 
Willy Denoyette said:
Use EnterpriseServices to run long running tasks and take advantage of a
bunch of services offered by ES.

Surely that's still going to be using another thread (or process, or
whatever) under the covers though, isn't it? If you've got something
which takes longer to process than you're prepared for the response to
take, you *have* to have something running in parallel.
 
Jon Skeet said:
Surely that's still going to be using another thread (or process, or
whatever) under the covers though, isn't it? If you've got something
which takes longer to process than you're prepared for the response to
take, you *have* to have something running in parallel.

Jon,

Sure, but my point was 'does the job need to run on a thread in the asp.net
worker process or not ?'.
To answer this question we need to know what OP meant with "a large job of
work" I guess.

If there are only very few parallel jobs, mostly IO bound (local and
network), that take only a few seconds to run, it's fine to run them on
their own thread inside asp.net.
However (and here is where ES comes in), if the job is CPU bound and can
take several minutes to run, you will need to run it outside asp.net,
possibly requiring message queuing system to control the asynchronous flow
of job requests/results.
If several such jobs need to run in parallel, you may even need to run it on
a separate box.

Willy.
 
Willy Denoyette said:
Sure, but my point was 'does the job need to run on a thread in the asp.net
worker process or not ?'.
To answer this question we need to know what OP meant with "a large job of
work" I guess.

If there are only very few parallel jobs, mostly IO bound (local and
network), that take only a few seconds to run, it's fine to run them on
their own thread inside asp.net.
However (and here is where ES comes in), if the job is CPU bound and can
take several minutes to run, you will need to run it outside asp.net,
possibly requiring message queuing system to control the asynchronous flow
of job requests/results.
If several such jobs need to run in parallel, you may even need to run it on
a separate box.

Why would it being CPU bound change that? You would want to put it in a
low priority thread, of course, but that's easily doable. What benefit
is there to putting it in a different process?

(If you need to run it on a separate box, of course, that means it's
absolutely *got* to be in a different process.)
 
Jon Skeet said:
Why would it being CPU bound change that? You would want to put it in a
low priority thread, of course, but that's easily doable. What benefit
is there to putting it in a different process?
Building asynchronous handlers to service "CPU bound" tasks only adds
threads to compete with the asp.net TP threads and will slow down the
overall processing time of the requests. Of course, you can lower the
priority of the asynchronous thread(s), but what if that job creates threads
of it's own?
So as I said before, all depends on what OP meant with a 'job' and what
other requirements are there imposed.
With "another process" I meant hosting a job in ES (COM+ ), this offers
advantages like process isolation, process recycling, call/activation and
memory quota control, security context management, object pooling etc.

Maybe somewhat OT, but just to give you and idea what I mean. I was one of
the architects and project leader of a web based Personal Banking
application that switches from in-proc asynchronous processing for some of
the transactions, to out-proc (ES/COM+) and remote (ES/COM+) processing
depending on the load (# of requests) the type of transactions (jobs), the
availability of the servers (planned/unplanned downtime) and the channels to
the back-end mainframe. This application took more than 20 man/year to
design implement and test, very soon we had to move to an out-proc model in
order to handle the load respecting the response/service time requirements.
Mainly because of availability and performance requirements, we had to
scale-out at the front-end (asp.net 1.0 beta didn't scale that well on MP
machines :-)) and the middle tier, so we moved some transactions to
dedicated servers (using ES/COM+). Now this applications handles ~4000
concurrent (authenticated) sessions with < 10 sec. response times for the
average real-time transactions.

Willy.
 
Back
Top