How many threads should a process possess?

Hi, everyone:

My application runs with its thread number ranging from 40 to more 60. I wonder how many threads a windows process should have. I have checked a lot only to find that the general MaxThreadNumber for ThreadPool is "25". But how about threads created by Thread.Start

Further more, after Thread.Start() was executed in my application, I was surprised to find the the thread may remain "Unstarted" under a uncertain condition which brings about a hang-up. Does this happen just because of too many threads in my application

Thank you



Answer this question

How many threads should a process possess?

  • Henrik Dahl

    As Nimrand stated there is no guarantee that a thread you start in Thread.Start will actually start before you get control back. It depends on the scheduler in the OS (and given this is embedded XP the rules are different than standard Windows probably). Nevertheless you should never assume that the method will return after the thread starts nor should you assume that it will never return before the thread starts. In theory if your thread does nothing it is possible that the thread you start completes before Thread.Start even returns.

    To realize my suggested approach of limiting threads (although if it is embedded then you could probably bump it up even higher as it is probably a dedicated device) you need to implement something similar to how the ThreadPool works. You would have one thread listening on a socket. When a request comes in you bundle the request up and push it to a shared queue and raise an OS event. One or more secondary queues (here is probably where your threads/processor determines the number of threads) listen for the OS event. When the event is raised only one of the threads gets released (use an AutoResetEvent) and that thread removes the request from the shared queue (using sync objects of course). The thread then does its work. When the thread is finished it waits for the OS event again. In this manner you can, in theory, handle up to X different requests where X is the # of threads you are running. If you put this into your config file you can change it without recompilation until you find a good balance between performance and throughput.

    There are variations to the above pattern and it only really works if your secondary threads that have to do the work won't block indefinitely. For example if the work you have to do involves communicating with another subsystem for minutes at a time then you really have no choice but to spawn secondary threads otherwise you'll block requests after your thread pool becomes saturated. Note that this is sort of how the thread pool works so if your threads really only do a little work and then return you could simply use the thread pool instead of managing your own threads. Of course your main listener thread would be a normal thread that you created but the worker threads could be from the thread pool.

    Michael Taylor - 6/26/06


  • chipjollyroger

    Thank you very much for your reply.

    My application is a background service without any graphics in Embedded XP. It has many connections with other subsystems. I have realized that too many threads is dangerous and began to decrease the number.But, the total threads number under my control is no more than 10 threads, how about the others  

    You see, .Net Remoting is used in my application, it seems that many threads are created to do the socket.Recv(). The more remoting is executed, the more threads are created. I have no idea of how to find who these threads are.I can only check the total thread number by "Windows task manager".

     TaylorMichaelL wrote:

    My personal approach is to assume that my app (and just my app) can use 2 threads per processor.  So if I'm running on a dual core processor then I can safely use up to 4 threads without any problems. 

    Well, your approach is splendid. I have no idea of how to realize it in my application. The current architecture is that a thread is waiting for a response or a command from a certain subsystem, when the signal is received, another thread or the thread itself brings this signal/event into a statemachine and do the proper response. Without these threads, are there any better method to realize a good response

    If pure socket API is used, I can use a thread to monitor many sockets between many subsystems, but for the convient Remoting, it seems impossible.

    Sincerely

    Sun


  • Gene R S

    You shouldn't have to terminate the thread necessarily as it will eventually start. However you can effectively block your main thread for a specific period of time by using a WaitHandle. You could have your secondary thread set an event on which your main thread can wait (with a timeout). This adds a new event per thread that you'll have to track though.

    //Main thread
    Thread.Start();
    if (!ThreadEvent.WaitOne(timeout))
    //Didn't start within a reasonable limit

    As for cancelling a thread there have been several articles written about it so you don't need to create your own. Here are some links:

    http://msdn.microsoft.com/msdnmag/issues/06/03/NETMatters/
    http://msdn.microsoft.com/msdnmag/issues/06/03/ConcurrentAffairs/
    http://www.ddj.com/dept/windows/188700792

    As for AutoResetEvent I am aware of no issues with it. I use it all the time without problems however in the embedded world there may be some issues. As for the driver stuff I can't knowledgeably answer those questions. You should post a separate question to the drivers forum to get some of the driver experts there to help you.

    Michael Taylor - 6/28/06




  • jgz

    There is no theoretical limit to the number of threads available but under standard Windows you are limited to approximately 2000 due to the default thread stack size. However you should never need this many and if your app is using 40 or more threads then you likely have a problem. Remember that Windows executes threads and not processes so if you are trying to run a single process with 40 threads then Windows is behind the scenes trying to schedule all threads. Even worse is that with that many threads you are probably spending far more time in the context switching then you are doing actual work. You really need to eliminate all those threads and switch to a queuing system to control the number of threads that get created.

    As for the magic number of threads that depends on circumstance. For IO bound threads having several is no big deal as generally IO processing occurs out-of-bounds provided you don't need the CPU to do any heavy lifting. However for threads that do large calculations you are going to get better performance by using only enough threads to cover the available number of processors so that each thread gets as much time out of the processors as possible. My personal approach is to assume that my app (and just my app) can use 2 threads per processor. So if I'm running on a dual core processor then I can safely use up to 4 threads without any problems. This is a good starting number and you can use performance counters and testing to determine the optimal # of threads for your app.

    As a final warning remember that Windows itself has a lot going on in the background. Also it is important to understand the environment you are going to be running in. On servers using multiple threads for a server app is fine provided you don't create multiple threads for each user. However on a single user machine it might be appropriate to create a couple of threads for the user since they are the only ones using the machine. The key is performance testing and using something like a config file setting to help manage the thread count so you can make changes and retest without recompilation.

    IMHO,
    Michael Taylor - 6/26/06


  • 12345_12345

    For your second question, it may be that Thread.Start does not immediately change the thread's state, but rather queues it to enter the running state. The documentation does not seem to indicate this, but I suppose its possible. Its also possible that the .NET Thread class has a minor bug such that it is returning you a cached (and thus, out-dated) thread state value rather than the actual current value. In either case, is there a way you can recode your app so that it doesn't hang if the thread doesn't seem to enter the running state immediately If you post some of your code, we many be able to spot where the problem is.
  • Petchey

    Thany you very much.

    Nimrand wrote:
    For your second question, it may be that Thread.Start does not immediately change the thread's state, but rather queues it to enter the running state. The documentation does not seem to indicate this, but I suppose its possible. Its also possible that the .NET Thread class has a minor bug such that it is returning you a cached (and thus, out-dated) thread state value rather than the actual current value.

    Do you mean the total thread number in "Running" state have reached the upper bound, and there were no space to let the so-called thread to changed its state If that is the case, why the state was not changed even serveral threads have finished If a bug exist, how can I find the batch

    Nimrand wrote:
    In either case, is there a way you can recode your app so that it doesn't hang if the thread doesn't seem to enter the running state immediately

    The general principal in our project is that a thread wating for a signal / commnad form other subsystems will generally create a new thread to pass the signal to upper object so as to receive another signal.

    Nimrand wrote:
    If you post some of your code, we many be able to spot where the problem is.

    Well, the code is simple. I could see the thread was in executing list, whereas the state is "Unstarted".

    Looking forward to your help.

    Sincerely

    Sun

  • Sylvain Arene

    Thank you very for your reply.I will have a good look at the attached site.

    TaylorMichaelL wrote:

    As for AutoResetEvent I am aware of no issues with it. I use it all the time without problems however in the embedded world there may be some issues.

    As for AutoResetEvent, I have the same problem with the folloing forum

    http://forums.microsoft.com/msdn/showpost.aspx postid=109596&siteid=1

    Alothough I was told that this problem was modified by KB827640, the so-called problem in AutoResetEvent is still a "problem" .

    Thank you!


  • GVA

    I don't claim to be an expert on threading, so please forgive my ignorance on the subject. I have read a lot of material about the dos and don'ts with threading. I've seen comments about thread pools and Work Items. So what approach is best for dealing with MMO games Here I might have 1000 people connected simultaneously sending and receiving data all of the time. If you are using async sockets with windows, which will use a pool of threads, sending and receiving are managed for you. But when data is going back and forth constantly, it would appear to me that the thread pool would get backed up, or end up expanding to 1-2 sockets per client anyway (sender and receiver). Essentially, I am looking at threads that may not spend very little time in the sleep state.

    The fact that I am using TCP sockets creates quite a bit of headache in that I do have this system where I have many connections and data is going back and forth constantly. In the case of UDP, I had a much simpler model where I had 2 threads (a sender and receiver), and simply worked to retrieve data from the single socket. Another thread would queue messages and dispatch them to the appropriate client interface. In this case, I only needed just a few threads and I could handle 1000s of clients. However, now, where I am being told that I have to use TCP, I see a lot more complication in managing this, as each individual socket is a blocking socket (ASYNC is nothing more than SYNC with a helper thread). Thus, all of these send and receives are going to require a lot of threads.

    So, I am stuck as to what direction I go. I would prefer to continue down the path using UDP, but it appear that is not an option, unless I get enough data to support that we should stick with UDP.

    I would sure appreciate any advice anyone has as to what I can do about this problem.




  • Hass Khan

    TaylorMichaelL wrote:

    As Nimrand stated there is no guarantee that a thread you start in Thread.Start will actually start before you get control back. It depends on the scheduler in the OS (and given this is embedded XP the rules are different than standard Windows probably). Nevertheless you should never assume that the method will return after the thread starts nor should you assume that it will never return before the thread starts. In theory if your thread does nothing it is possible that the thread you start completes before Thread.Start even returns.

    I see. Therefore, something linke a timer mechanism is necessary here to brings the process to an end if the expected thread doesn't start. In this case, ThreadPool mechenism of .NET cannot be used because you can not cancel a thread you invoked be BeginInvoke. So, I created a ThreadManager of my own to keep track of the thread handlers.

    TaylorMichaelL wrote:

    To realize my suggested approach of limiting threads (although if it is embedded then you could probably bump it up even higher as it is probably a dedicated device) you need to implement something similar to how the ThreadPool works. You would have one thread listening on a socket. When a request comes in you bundle the request up and push it to a shared queue and raise an OS event. One or more secondary queues (here is probably where your threads/processor determines the number of threads) listen for the OS event. When the event is raised only one of the threads gets released (use an AutoResetEvent) and that thread removes the request from the shared queue (using sync objects of course). The thread then does its work. When the thread is finished it waits for the OS event again. In this manner you can, in theory, handle up to X different requests where X is the # of threads you are running. If you put this into your config file you can change it without recompilation until you find a good balance between performance and throughput.

    This is indeed a good approach. But it seems there some bugs in AutoResetEvent. I am trying my best to avoid using AutoResetEvent. But it is very troublesome that no other mechanism is better than AutoResetEvent sometimes.

    TaylorMichaelL wrote:

    There are variations to the above pattern and it only really works if your secondary threads that have to do the work won't block indefinitely. For example if the work you have to do involves communicating with another subsystem for minutes at a time then you really have no choice but to spawn secondary threads otherwise you'll block requests after your thread pool becomes saturated. Note that this is sort of how the thread pool works so if your threads really only do a little work and then return you could simply use the thread pool instead of managing your own threads. Of course your main listener thread would be a normal thread that you created but the worker threads could be from the thread pool.

    It seems I have to reconsider the whole architecture of my program. Would you give me some advice on Windows drivers That is , in case of design a wrapper to monitor PCI devices, it don't think it is proper to setup a thread for each board. Should a working thread polling each device at a certain interval What should be the priority of this thread Is "TimeCritical" dangerous I think this priority may freeze the main thread of a windows application.

    Yours Sincerely


  • How many threads should a process possess?