C# 我什么时候不应该在 .Net 中使用 ThreadPool?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-07-31 17:35:17  来源:igfitidea点击:

When should I not use the ThreadPool in .Net?

提问by Vaibhav

When should I notuse the ThreadPool in .Net?

什么时候不应该在 .Net 中使用 ThreadPool?

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?

你在这方面有什么经验?

采纳答案by Derek Park

The only reason why I wouldn't use the ThreadPoolfor cheap multithreading is if I need to…

我不使用ThreadPool廉价多线程的唯一原因是如果我需要……

  1. interract with the method running (e.g., to kill it)
  2. run code on a STA thread(this happened to me)
  3. keep the thread alive after my application has died (ThreadPoolthreads are background threads)
  4. 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.
  1. 与正在运行的方法交互(例如,杀死它)
  2. STA 线程上运行代码(这发生在我身上)
  3. 在我的应用程序死后保持线程处于活动状态(ThreadPool线程是后台线程)
  4. 如果我需要更改线程的优先级。我们无法更改 ThreadPool 中线程的优先级,默认情况下为 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.

PS:MSDN 文章“托管线程池”包含一个标题为“何时不使用线程池线程”的部分,其中列出了不使用线程池的可能原因非常相似但稍微更完整的列表。

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

有很多的,你为什么会需要跳过的原因ThreadPool,但如果你不知道他们那么ThreadPool应该是配不上你。

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.

或者,看看新的Parallel Extensions Framework,其中有一些简洁的东西,可以满足您的需求,而无需使用ThreadPool.

回答by Quibblesome

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.

当您要执行一个需要很长时间的操作时,或者可能是一个连续的后台线程。我想你总是可以增加池中可用线程的数量,但是产生一个永远不会返回到池中的线程的管理成本是没有意义的。

回答by Derek Park

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.

当您需要执行完全不同且不相关的操作(不能被视为“作业”)的线程时,线程池没有意义;例如,一个用于 GUI 事件处理的线程,另一个用于后端处理。当处理形成管道时,线程池也没有意义。

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.

基本上,如果您有启动、处理作业和退出的线程,那么线程池可能是最佳选择。否则,线程池不会真正有帮助。

回答by Dogmang

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.

为了争吵的答案,我想补充一点,如果您需要保证您的线程将立即开始工作,最好不要使用 ThreadPool 线程。每个应用程序域的运行线程池线程的最大数量是有限的,因此如果它们都忙,您的工作可能必须等待。毕竟,它被称为“队列用户工作项”。

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.
  1. 您可以在运行时更改代码中线程池线程的最大数量,因此没有什么可以阻止您检查当前与最大数量并在需要时增加最大值。
  2. 启动一个新线程会带来自己的时间损失 - 您是否值得接受打击取决于您的情况。

回答by Derek Park

@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.

@Eric,我将不得不同意 Dean。线程很贵。您不能假设您的程序是唯一运行的程序。当每个人都对资源贪婪时,问题就会成倍增加。

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();  
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.

我希望您通常会在Start()和之间添加一些额外的代码Join()。否则,额外的线程是无用的,你就是在无缘无故地浪费资源。

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.

人们太害怕线程使用的资源。我从未见过创建和启动线程花费超过一毫秒的时间。您可以创建的线程数没有硬性限制。RAM 使用量很小。一旦你有几百个线程,CPU 就会因为上下文切换而成为一个问题,所以在这一点上你可能想要对你的设计感兴趣。

A millisecond is a longtime 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.

在现代硬件上,一毫秒是很长的时间。这是 3GHz 机器上的 300 万个周期。而且,您并不是唯一一个创建线程的人。您的线程与所有其他程序的线程一起争夺 CPU。如果您使用的线程不是太多,另一个程序也是如此,那么您一起使用了太多的线程。

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?

的确。不要让生活变得更复杂。如果您的程序需要多个工作线程,请不要重新发明轮子。使用线程池。这就是为什么它在那里。你会推出自己的字符串类吗?

回答by Derek Park

@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.

@Derek,我不完全同意您用作示例的场景。如果您不确切知道您的机器上正在运行什么,以及您的应用程序在一定负载量下将使用多少线程、句柄、CPU 时间、RAM 等,那么您就有麻烦了。

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.

您是您编写的程序的唯一目标客户吗?如果没有,您就无法确定其中的大部分内容。当您编写程序时,您通常不知道它是否会单独有效地执行,或者它是否会在受到 DDOS 攻击的网络服务器上运行。您无法知道将拥有多少 CPU 时间。

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.

假设您的程序的行为根据输入而变化,甚至很难确切知道您的程序将消耗多少内存或 CPU 时间。当然,您应该对您的程序将如何运行有一个很好的了解,但是大多数程序从未被分析过以确定将使用多少内存、多少句柄等,因为完整的分析是昂贵的。如果您不是在编写实时软件,那么付出的努力是不值得的。

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.

我的大部分专业经验都与多线程和多处理程序有关。我也经常需要推出自己的解决方案。这并不意味着线程池在许多情况下没有用或不合适。线程池用于处理工作线程。在适合多个工作线程的情况下,提供的线程池通常应该是第一种方法。

回答by Will Dean

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.

啊,来自权威的争论——但要时刻注意可能在 Windows 内核团队中工作的人。

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.

我们都没有争论这样一个事实,即如果您有一些特定的要求,那么 .NET ThreadPool 可能不是正确的东西。我们反对的是将创建线程的机器的成本微不足道。

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.

首先为 ThreadPool 创建一个线程的存在的理由是巨大的开销。我不希望我的机器充满那些被误解创建线程的费用的人编写的代码,例如,不知道它会导致在每个单独的 DLL 中调用一个方法,这是附加到进程(其中一些将由第 3 方创建),并且很可能会加热一些根本不需要在 RAM 中并且几乎肯定不需要在 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.

现代机器中内存层次结构的形状意味着“分散”CPU 是你可能做的最糟糕的事情,每个关心他们的工艺的人都应该努力避免它。

回答by hwiechers

MSDN has a list some reasons here:

MSDN 在这里列出了一些原因:

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

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 线程都在多线程单元中。
  • 您需要具有与线程关联的稳定身份,或者将线程专用于任务。

回答by supercat

Threadpool threads are appropriate for tasks that meet both of the following criteria:

线程池线程适用于同时满足以下两个条件的任务:

  1. The task will not have to spend any significant time waiting for something to happen
  2. 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.
  1. 任务不必花费大量时间等待某事发生
  2. 任何等待任务完成的东西很可能会等待许多任务完成,所以它的调度优先级不太容易影响事情。

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.

使用线程池线程而不是创建新线程将节省大量但有限的时间。如果该时间与执行任务所需的时间相比很重要,则线程池任务可能是合适的。然而,执行任务所需的时间越长,使用线程池的好处就越小,任务阻碍线程池效率的可能性就越大。