Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / June 2006

Tip: Looking for answers? Try searching our database.

NOT using the System.Threadpool in server class applications

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Chris Mullins - 27 Jun 2006 05:24 GMT
Quite often of late I've been asked about when to use the System Threadpool.

I finally sat down and wrote a blog detailing the issues in the ThreadPool
and why it's unsuitable for use in production grade server applications.

Any feedback on this is appriciated!

http://www.coversant.net/dotnetnuke/Coversant/Blogs/tabid/88/EntryID/8/Default.aspx

Signature

Chris Mullins

Jon Skeet [C# MVP] - 27 Jun 2006 07:19 GMT
> Quite often of late I've been asked about when to use the System Threadpool.
>
[quoted text clipped - 4 lines]
>
> http://www.coversant.net/dotnetnuke/Coversant/Blogs/tabid/88/EntryID/8/Default.aspx

My only feedback is that this is something I've been aware of for a
while. When I tried to make the same point on the CLR mailing list, I
was variously accused of being naive or finding problems when there
really aren't any.

Half the problem is that *anything* can use the system threadpool -
there's no way of isolating different areas of code to use different
pools.

Oh well - at least I'm not alone in considering it a problem.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Chris Mullins - 27 Jun 2006 18:22 GMT
> Chris Mullins <cmullins@yahoo.com> wrote:
>>
>> http://www.coversant.net/dotnetnuke/Coversant/Blogs/tabid/88/EntryID/8/Default.aspx

[Jon has seen this too]

> My only feedback is that this is something I've been aware of for a
> while. When I tried to make the same point on the CLR mailing list, I
> was variously accused of being naive or finding problems when there
> really aren't any.

That's what I've been bumping into as well. I dismiss alot of it, as its
from people who write proof-of-concept applications for a living, rather
than production grade applications. As we all know, there's a world of
difference between them.

> Half the problem is that *anything* can use the system threadpool -
> there's no way of isolating different areas of code to use different
> pools.

Yea, I agree. This was, when we ran into this 3 years or so ago, the big
issue. We needed the ability to say, "CLR gets these threads, SoapBox Server
gets these threads". Without that ability, the threadpool runs out of
threads and the whole appdomain hangs.

Signature

Chris Mullins

William Stacey [MVP] - 28 Jun 2006 05:51 GMT
Here is rough pseudocode for a server that uses a threadpool (the clr or
other)
to handle N client sockets. We break a TP rule here because we use a
threadpool thread
for a long running operation (i.e. the socket read). However, it is our
server, so we
understand and manage that issue. Basically, we add all client sockets to a
list - for management, etc. We then kick off the first read (and future
reads) on a thread pool thread.
We set a max of threads to 100 in this example. So at any one instant, we
could have a 100 pending reads. Other client reads will just queue up in the
TP FIFO queue.

Issues:
1) 100 slow clients (in this example) can stall the TP. This could be an
attack, or just 100 slow clients. We can mitigate attack by only allowing so
many connections from same IP. Other methods, such as an async server, can
also stall after many pending reads, so not sure how much of issue this is
in reality compared to other methods. After a client does a read/reply, it
frees that thread and posts another read to the queue so other clients get
time. The next client in the queue gets to read so the server will keep
running as long as client reads eventually happen.
2) Writes are done sync on the same thread. Not sure this is much of an
issue however. The write will be done quickly with no wait. Not sure we gain
anything by doing an async write.

Advantages:
1) Built in fairness. Client requests are handled FIFO.
2) Dynamic throttle. We can throttle and apply "back-pressure" just by
changing the number of MaxThreads in the TP. This will limit the number of
pending sync reads/readprocessing on the server at any one time. New clients
just queue up.
3) Logic is sync. However we don't assign 1 thread per client for the whole
client session. Each request/reply will be handle by another TP thread
(possibly the same if Q is empty). This makes it easy to code and find bugs.
We can also use the socket timeout feature on reads and writes. Slow clients
that timeout can just be dropped (or use some algo). After a timeout, we
free that thread for another client read.
4) Easy to replace system TP with a custom TP if needed.
5) Can handle many thousands of clients with little number of threads. Only
testing we find the optimal number of threads needed for the app.

PseudoCode (just the basics. Locks, exception handling, etc, not shown for
simplicity):
---------------------------------------------------------------------------------------
ThreadPool.MinThreads = 25;
ThreadPool.MaxThreads = 100;

while(started)
{
  sock = Accept();
  sock.ReadTimeout = 5000;
  if ( userList.Count > 5000 ) // Set to how many concurrent clients you
want.
  {
     sock.Close(); //A hard close - too many clients. Can do this better.
     continue;
  }
  userList.Add(sock);

  // Kick off the request/response chain for client.
  ThreadPool.QueueUserWorkItem(ReadMethod, sock);
}

private void ReadMethod(object state)
{
  // This is on a threadpool thread.
  //
  Socket sock = (Socket)state;
  byte[] buf = new byte[1024];
  try
  {
     int read = sock.Receive(buf);

     // Handle request processing.

     // Write reply back to client.
     sock.Send(writebuf);
     if ( done )
     {
        sock.Close()
        userList.Remove(sock);
        return; // Client done.
     }

     // Release this thread to pool, but queue another read before we
leave.
     // Note: If there is no other queued work items,
     // the TP will most likely just use the same thread.
     ThreadPool.QueueUserWorkItem(ReadMethod, sock);
  }
  catch(Timeout te)
  {
      //Handle timeout.
  }
  catch(Exception ex)
  {
      //Handle exception
  }
}

Signature

William Stacey [MVP]

| Quite often of late I've been asked about when to use the System Threadpool.
|
| I finally sat down and wrote a blog detailing the issues in the ThreadPool
| and why it's unsuitable for use in production grade server applications.
|
| Any feedback on this is appriciated!

http://www.coversant.net/dotnetnuke/Coversant/Blogs/tabid/88/EntryID/8/Default.aspx

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.