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.
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.
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:
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.
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.
@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, 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.
There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads:
You require a foreground thread.
You require a thread to have a particular priority.
You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.
You need to place threads into a single-threaded apartment. All ThreadPool threads are in the multithreaded apartment.
You need to have a stable identity associated with the thread, or to dedicate a thread to a task.
Threadpool threads are appropriate for tasks that meet both of the following criteria:
The task will not have to spend any significant time waiting for something to happen
Anything that's waiting for the task to finish will likely be waiting for many tasks to finish, so its scheduling priority isn't apt to affect things much.
Using a threadpool thread instead of creating a new one will save a significant but bounded amount of time. If that time is significant compared with the time it will take to perform a task, a threadpool task is likely appropriate. The longer the time required to perform a task, however, the smaller the benefit of using the threadpool and the greater the likelihood of the task impeding threadpool efficiency.
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.
keep the thread alive after my application has died (ThreadPool threads are background threads)
in case I need to change the priority of the Thread. We can not change priority of threads in ThreadPool which is by default Normal.
P.S.: The MSDN article "The Managed Thread Pool" contains a section titled, "When Not to Use Thread Pool Threads", with a very similar but slightly more complete list of possible reasons for not using the thread pool.
There are lots of reasons why you would need to skip the ThreadPool, but if you don't know them then the ThreadPool 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 ThreadPool.
发布评论
评论(9)
只要您有工作线程的概念,线程池就有意义。 每当您可以轻松地将处理划分为较小的作业(每个作业都可以独立处理)时,工作线程(因此线程池)就有意义。
当您需要执行完全不同且不相关的操作(不能被视为“作业”)的线程时,线程池没有意义; 例如,一个线程用于 GUI 事件处理,另一个线程用于后端处理。 当处理形成管道时,线程池也没有意义。
基本上,如果您有启动、处理作业和退出的线程,那么线程池可能是最佳选择。 否则,线程池并没有真正的帮助。
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.
啊,来自权威的论据 - 但始终要留意可能属于 Windows 内核团队的人员。
我们都没有争论这样一个事实:如果您有一些特定的要求,那么 .NET ThreadPool 可能不是正确的选择。 我们反对的是使创建线程的机器成本变得微不足道。
首先,为 ThreadPool 存在的理由是创建线程的巨大开销。 我不希望我的机器中充满了那些对创建线程的费用有误解的人编写的代码,并且不知道它会导致在每个 DLL 中调用一个方法,该方法是附加到进程(其中一些将由第 3 方创建),并且很可能会热加载根本不需要在 RAM 中并且几乎肯定不需要在 L1 中的代码负载。
现代机器中内存层次结构的形状意味着“分散”CPU 的注意力可能是最糟糕的事情,每个关心自己技术的人都应该努力避免这种情况。
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.
对于 quarrelsome 的回答,我想补充一点,如果您需要保证线程立即开始工作,最好不要使用 ThreadPool 线程。 每个应用程序域运行的线程池线程的最大数量是有限的,因此如果它们都很忙,您的工作可能必须等待。 毕竟,它被称为“队列用户工作项”。
当然,有两个警告:
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:
@Eric,我必须同意迪恩的观点。 线程很昂贵。 您不能假设您的程序是唯一正在运行的程序。 当每个人都对资源贪婪时,问题就会成倍增加。
合适的时候就好了。 但是,如果您需要一堆工作线程,那么您所做的就是使代码变得更加复杂。 现在您必须编写代码来管理它们。 如果您只使用线程池,您将免费获得所有线程管理。 而且该语言提供的线程池很可能比您自己使用的任何线程池更健壮、更高效且错误更少。
我希望您通常会在
Start()
和Join()
之间添加一些额外的代码。 否则,额外的线程是无用的,并且您无缘无故地浪费资源。对于现代硬件来说,毫秒是一个很长的时间。 这在 3GHz 机器上是 300 万个周期。 再说一遍,您并不是唯一一个创建线程的人。 您的线程与所有其他程序的线程一起竞争 CPU。 如果您使用的线程不是太多,而另一个程序也是如此,那么您总共使用了太多的线程。
的确。 不要让生活变得更加复杂。 如果您的程序需要多个工作线程,请不要重新发明轮子。 使用线程池。 这就是它存在的原因。 你会推出自己的字符串类吗?
@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.
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.
I hope that you would normally have some additional code in between
Start()
andJoin()
. Otherwise, the extra thread is useless, and you're wasting resources for no reason.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.
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?
@埃里克
您是您编写的程序的唯一目标客户吗? 如果没有,您就无法确定其中的大部分内容。 当您编写程序时,您通常不知道它是否会有效地单独执行,或者是否会在受到 DDOS 攻击的网络服务器上运行。 您无法知道将拥有多少 CPU 时间。
假设您的程序的行为根据输入而变化,甚至很难确切知道您的程序将消耗多少内存或 CPU 时间。 当然,您应该对程序的行为有一个很好的了解,但大多数程序从未被分析来确定将使用多少内存、多少句柄等,因为完整的分析是昂贵的。 如果您不编写实时软件,那么付出的努力就不值得。
一般来说,声称准确地了解程序的行为方式是牵强的,而声称了解有关机器的一切则显得可笑。
我并不完全不同意,但我真的不明白这有什么关系。 这个网站之所以设立在这里,是因为程序员并不总能找到所有答案。
不。如果我需要一个线程池,我将使用提供的线程池,除非并且直到我发现它还不够。 在没有确认情况的情况下,我不会简单地假设提供的线程池不足以满足我的需求。
我的大部分专业经验都是与多线程和多处理程序有关。 我也经常需要推出自己的解决方案。 这并不意味着线程池在许多情况下没有用或不合适。 线程池是为了处理工作线程而构建的。 在适合多个工作线程的情况下,提供的线程池通常应该是第一种方法。
@Eric
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.
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.
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.
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.
MSDN 在这里列出了一些原因:
http://msdn.microsoft.com/en -us/library/0ka9477y.aspx
MSDN has a list some reasons here:
http://msdn.microsoft.com/en-us/library/0ka9477y.aspx
线程池线程适用于满足以下两个条件的任务:
使用线程池线程而不是创建新线程将节省大量但有限的时间。 如果该时间与执行任务所需的时间相比很重要,则线程池任务可能是合适的。 然而,执行任务所需的时间越长,使用线程池的好处就越小,并且任务阻碍线程池效率的可能性就越大。
Threadpool threads are appropriate for tasks that meet both of the following criteria:
Using a threadpool thread instead of creating a new one will save a significant but bounded amount of time. If that time is significant compared with the time it will take to perform a task, a threadpool task is likely appropriate. The longer the time required to perform a task, however, the smaller the benefit of using the threadpool and the greater the likelihood of the task impeding threadpool efficiency.
当您要执行一项需要很长时间或可能需要连续后台线程的操作时。
我想你总是可以增加池中可用的线程数量,但是对于永远不会返回到池中的线程来说,产生管理成本是没有意义的。
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.
我不会使用 ThreadPool 来实现廉价的多线程的唯一原因是,如果我需要...
ThreadPool
线程是后台线程),您需要跳过 ThreadPool 的原因有很多,但如果您不了解它们,那么 ThreadPool 应该足够适合您了。
或者,查看新的 并行扩展框架,其中有一些巧妙的东西可以满足您的需求,而无需使用
ThreadPool
。The only reason why I wouldn't use the
ThreadPool
for cheap multithreading is if I need to…ThreadPool
threads are background threads)There are lots of reasons why you would need to skip the
ThreadPool
, but if you don't know them then theThreadPool
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
ThreadPool
.