views:

2268

answers:

8

When should I not use the ThreadPool in .Net?

it looks like the best option is to use a ThreadPool. In which case, why is it not the only option.

What are your experiences around this?

+1  A: 

When you're going to perform an operation that is going to take a long time, or perhaps a continuous background thread. I guess you could always push the amount of threads available in the pool up but there would be little point in incurring the management costs of a thread that is never going to be given back to the pool.

Quibblesome
+3  A: 

Thread pools make sense whenever you have the concept of worker threads. Any time you can easily partition processing into smaller jobs, each of which can be processed independently, worker threads (and therefore a thread pool) make sense.

Thread pools do not make sense when you need thread which perform entirely dissimilar and unrelated actions, which cannot be considered "jobs"; e.g., One thread for GUI event handling, another for backend processing. Thread pools also don't make sense when processing forms a pipeline.

Basically, if you have threads which start, process a job, and quit, a thread pool is probably the way to go. Otherwise, the thread pool isn't really going to help.

Derek Park
Can you explain the remark "thread pools don't make sense when processing forms a pipeline"? Suppose I have work items that need to be compressed, then encrypted, and compression uses 10x the compute as encryption. Why not use a threadpool with a 10:1 ratio of compressor to encryptor threads?
Cheeso
Thread pools are generally for when a program has independent, discrete pieces of work to do. If there's communication between the worker threads (such as in a pipeline), then you don't really have a thread pool scenario.
Derek Park
A: 

Huh?

The only reason why I wouldn't use the ThreadPool for cheap multithreading is if I 1) needed to interract with the method running (i.e., needed to kill it), 2) needed to run code on a STA thread (this happened to me), 3) Need to keep the thread alive after my app has died (TP threads are background threads), 4) etc.

There are lots of reasons why you would need to skip the ThreadPool, but if you don't know them then the TP should be good enough for you.

Alternatively, look at the new Parallel Extensions Framework, which has some neat stuff in there that may suit your needs without having to use the TP.

Will
+2  A: 

To quarrelsome's answer, I would add that it's best not to use a ThreadPool thread if you need to guarantee that your thread will begin work immediately. The maximum number of running thread-pooled threads is limited per appdomain, so your piece of work may have to wait if they're all busy. It's called "queue user work item", after all.

Two caveats, of course:

  1. You can change the maximum number of thread-pooled threads in code, at runtime, so there's nothing to stop you checking the current vs maximum number and upping the maximum if required.
  2. Spinning up a new thread comes with its own time penalty - whether it's worthwhile for you to take the hit depends on your circumstances.
Dogmang
+1  A: 

People are way too afraid of the resources used by threads.

Or perhaps the opposite, that people are way too casually selfish with the resources of a shared computer, and fail to think through all the concurrency issues of something like creating a thread.

Creating threads is expensive, which is why people have gone to the trouble of creating things like thread-pools and asynchronous delegates and I/O techniques.

Will Dean
+14  A: 

@Eric, I'm going to have to agree with Dean. Threads are expensive. You can't assume that your program is the only one running. When everyone is greedy with resources, the problem multiplies.

I prefer to create my threads manually and control them myself. It keeps the code very easy to understand.

That's fine when it's appropriate. If you need a bunch of worker threads, though, all you've done is make your code more complicated. Now you have to write code to manage them. If you just used a thread pool, you'd get all the thread management for free. And the thread pool provided by the language is very likely to be more robust, more efficient, and less buggy than whatever you roll for yourself.

Thread t = new Thread(new ThreadStart(DoSomething));
t.Start();
t.Join();

I hope that you would normally have some additional code in between Start() and Join(). Otherwise, the extra thread is useless, and you're wasting resources for no reason.

People are way too afraid of the resources used by threads. I've never seen creating and starting a thread to take more than a millisecond. There is no hard limit on the number of threads you can create. RAM usage is minimal. Once you have a few hundred threads, CPU becomes an issue because of context switches, so at that point you might want to get fancy with your design.

A millisecond is a long time on modern hardware. That's 3 million cycles on a 3GHz machine. And again, you aren't the only one creating threads. Your threads compete for the CPU along with every other program's threads. If you use not-quite-too-many threads, and so does another program, then together you've used too many threads.

Seriously, don't make life more complex than it needs to be. Don't use the thread pool unless you need something very specific that it offers.

Indeed. Don't make life more complex. If your program needs multiple worker threads, don't reinvent the wheel. Use the thread pool. That's why it's there. Would you roll your own string class?

Derek Park
Some people rolls their own wrapper over an array of char's and use it like a string.. so it's possible... and it's sad too.
Andrei Rinea
A: 

@Eric

@Derek, I don't exactly agree with the scenario you use as an example. If you don't know exactly what's running on your machine and exactly how many total threads, handles, CPU time, RAM, etc, that your app will use under a certain amount of load, you are in trouble.

Are you the only target customer for the programs you write? If not, you can't be certain about most of that. You generally have no idea when you write a program whether it will execute effectively solo, or if it will run on a webserver being hammered by a DDOS attack. You can't know how much CPU time you are going to have.

Assuming your program's behavior changes based on input, it's rare to even know exactly how much memory or CPU time your program will consume. Sure, you should have a pretty good idea about how your program is going to behave, but most programs are never analyzed to determine exactly how much memory, how many handles, etc. will be used, because a full analysis is expensive. If you aren't writing real-time software, the payoff isn't worth the effort.

In general, claiming to know exactly how your program will behave is far-fetched, and claiming to know everything about the machine approaches ludicrous.

And to be honest, if you don't know exactly what method you should use: manual threads, thread pool, delegates, and how to implement it to do just what your application needs, you are in trouble.

I don't fully disagree, but I don't really see how that's relevant. This site is here specifically because programmers don't always have all the answers.

If your application is complex enough to require throttling the number of threads that you use, aren't you almost always going to want more control than what the framework gives you?

No. If I need a thread pool, I will use the one that's provided, unless and until I find that it is not sufficient. I will not simply assume that the provided thread pool is insufficient for my needs without confirming that to be the case.

I'm not speaking as someone with only theoretical knowledge here. I write and maintain high volume applications that make heavy use of multithreading, and I generally don't find the thread pool to be the correct answer.

Most of my professional experience has been with multithreading and multiprocessing programs. I have often needed to roll my own solution as well. That doesn't mean that the thread pool isn't useful, or appropriate in many cases. The thread pool is built to handle worker threads. In cases where multiple worker threads are appropriate, the provided thread pool should should generally be the first approach.

Derek Park
+1  A: 

I'm not speaking as someone with only theoretical knowledge here. I write and maintain high volume applications that make heavy use of multithreading, and I generally don't find the thread pool to be the correct answer.

Ah, argument from authority - but always be on the look out for people who might be on the Windows kernel team.

Neither of us were arguing with the fact that if you have some specific requirements then the .NET ThreadPool might not be the right thing. What we're objecting to is the trivialisation of the costs to the machine of creating a thread.

The significant expense of creating a thread at the raison d'etre for the ThreadPool in the first place. I don't want my machines to be filled with code written by people who have been misinformed about the expense of creating a thread, and don't, for example, know that it causes a method to be called in every single DLL which is attached to the process (some of which will be created by 3rd parties), and which may well hot-up a load of code which need not be in RAM at all and almost certainly didn't need to be in L1.

The shape of the memory hierarchy in a modern machine means that 'distracting' a CPU is about the worst thing you can possibly do, and everybody who cares about their craft should work hard to avoid it.

Will Dean