HttpWebRequest ThreadPool usage - strange behaviour

I

icesunny

I posted this at dotnet.general a few days ago, but as far as there was
no answer, I'll repost it here. I you think that there is even more
appropriate group for this, please let me know, and I'll repost. Thanks.

<Repost>

Hi,
I read a lot of articles about deadlocks and ThreadPool overloading when
a lot of WebService or WebRequests are made from and ASP.NET
applications. In most of these articles and examples there is a
statement, that HttpWebRequest.GetResponse() call is always executed
asyncronously in v. 1.x of the network. I used Reflector to examine
this, and indeed, the code looks like:

BeginGetRequest(...);
.......
EndGetRequest();

Now, I created a test console application, which invokes a simple web
service. This service only invokes Thread.Sleep for the number of
seconds passed as parameter. Note - this is for .Net v.1.1 SP1.

My test application starts 3 threads (not from the threadpool). The
first one prints on console the current ThreadPool free threads. And the
other 2 make invocation of the sample web service (not using a proxy,
but pure GET request, using HttpWebRequest class), requesting delays of
10 and 20 seconds.

Now, the strange thing is, that I do not see any thread of the
ThreadPool used while waiting for the HttpResponse, I.e. this behaves
very differently from what I read so far about how HttpRequests are
made.

I tried to invoke HttpWebRequest in 3 different ways (just comment and
uncomment the corresponding 2 lines in the Main method):

1. A custom thread just invokes the synchronous GetResponse method - no
threadpool usage is visible, even as per the articles I mentioned, it
should translate in async invocation internally.

2. A threadpool thread invokes synchronous GetResponse - then obviously
a threads from the pool are used, but only the ones, which make the
call, but still not visible another threadpool thread which is used by
the GetResponse.

3. A custom thread, which invokes async GetResponse (with
BeginGetResponse/EndGetResponse), as well as async reading of the
response stream. Still I can not see a threadpool thread to be used.

Can somebody explain this behaviour? Why this sample works not like it
should be? If all these articles are wrong, should I worry if I have a
async web service, which internally invokes a 100-200 HttpRequests per
invocation. I may have more than 300 invocations of that service in the
same time?

Actually, what I'm after is a web service, which will be used by more
than 300 clients at the same time, which by itself retrieves 100-200 web
pages per request. I want to speedup the process, and to use all
available resources to fetch as many pages as possible at a time using
threads.

At the following URL you can find a zip with the source files I used.
You need to set your IIS virtual directory to map to the test web
service:
http://216.17.90.93/ThreadTest.zip



These are the articles I read on the topic:

<http://msdn.microsoft.com/msdnmag/issues/04/12/NETMatters/>
<http://www.deez.info/sengelha/blog/2005/03/03/beware-threadpools-and-
httpwebrequest/>
<http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/dnservice/html/service07222003.asp>
<http://msdn.microsoft.com/msdnmag/issues/03/06/Threading/>

Cheers
Sunny
 
P

Peter Huang [MSFT]

Hi Sunny,

Currently you are trying to track how the GetResponse in .NET 1.1. running.
You wondering it is not using the ThreadPool threads by checking the
GetAvailableThreads method.

Based on my research, the interval 1000 to check the GetAvailableThreads is
too large, you may try to use the approach below to check you will find
that the value will change.
private static void DisplayStatus()
{
while (true)
{
int worker;
int conn;
ThreadPool.GetAvailableThreads(out worker, out conn);
if(worker!=25 || conn!=1000)
Console.WriteLine("{0}: Available: Worker: {1}, conn: {2}",
DateTime.Now, worker, conn);
Thread.Sleep(0);
}
}

By default, the worker = 25 and conn = 1000, but the method above will
display the value when the worker is not 25 and the conn is not 1000.

Actually in the article you mentioned, the GetResponse method internally
will check the available thread in the threadpool, note, this is a internal
method.
internal static bool IsThreadPoolLow()
{
int num1;
int num2;
if (ComNetOS.IsAspNetServer)
{
return false;
}
ThreadPool.GetAvailableThreads(out num1, out num2);
if ((num1 >= 2) && (!ComNetOS.IsWinNt || (num2 >= 2)))
{
return false;
}
return true;
}

So I think you do not need to check at by yourself.

Also in .NET 2.0 the problem is fixed, because the GetResponse will no long
running asynchronously.

Actually I did not suggest you running too many threads in one process,
this is why CLR internally suggest the worker threads to be 25. Because
actually it is the CPU to run the code, even if we have many threads, but
if there is only one CPU, actually there will be only one thread running in
the same time.


Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Sunny

Hi Peter,
Now I can see what happens. I added a delay (10 secs) in the callback
function, and then I could see that IO threadpool threads are used. But
then, still all these articles are wrong in terms that they always speak
about the 25 per processor limitation, while it uses the IO threads. I
tried on different machines, and while the regular threadpool thread
(the 25 per processor ones) do increase based on the number of
processors, the IO threads are always 1000, so they do not depend on the
number of processors. It is strange that this is not discussed anywhere.

Is there any article/documentation, etc., which explains which framework
methods use which part of the threadpool? Looks like an async delegate
invocation uses the first part (25 per processor). But what threadpool
is used with remoting, or by async web services, etc.? What threads are
going to be used if I implement async HTTP handler, as described in
these articles?

Cheers
Sunny
 
P

Peter Huang [MSFT]

Hi Sunny,

Based on my research, I did not find such a document about the .NET method
implementation concerned of ThreadPool.

But generally as you said, if we use async delegate invoke, it should be on
Worker thread, we can considered all the IO related
operation(socket/network, file...) on the IO Threads.
The HttpWebRequest will call into Socket related network method, we also
considered them as IO threads.

But the other non IO related should be on the worker t hreads.

Also the design on the ThreadPool should be used to help the developer to
control/manage the thread schedule, the dev should not care its implement,
if you want to control over more detailed information, it would better
create/manage thread ourself, but not ThreadPool.

We could simply query the GetAvailableThreads to know if the ThreadPool is
busy, if no, we just put the job into ThreadPool and wait for return.

Best regards,

Peter Huang

Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
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

Top