什么时候不应该在.Net中使用ThreadPool?
什么时候不应该在.Net中使用ThreadPool?
看起来最好的select是使用ThreadPool,在这种情况下,为什么它不是唯一的select?
你有什么经验呢?
为什么我不会使用ThreadPool
廉价的multithreading的唯一原因是,如果我需要…
- 与运行的方法进行交互(例如,杀死它)
- 在STA线程上运行代码(这发生在我身上)
- 我的应用程序已经死亡后保持线程活着(
ThreadPool
线程是后台线程) - 如果我需要改变线程的优先级。 我们不能改变ThreadPool中默认为Normal的线程的优先级。
PS: MSDN文章“托pipe线程池”包含标题为“何时不使用线程池线程”的部分 ,其中包含非常相似但略有更完整的不使用线程池的原因列表。
有很多原因需要跳过ThreadPool
,但是如果你不知道它们,那么ThreadPool
应该足够适合你。
或者,看看新的并行扩展框架 ,其中有一些整洁的东西,可能适合您的需要,而无需使用ThreadPool
。
@Eric,我不得不同意Dean的意见。 线程是昂贵的。 你不能认为你的程序是唯一运行的程序。 当每个人都贪婪的资源,问题倍增。
我更喜欢手动创build我的线程,并自己控制它们。 它使代码非常容易理解。
这很合适。 如果你需要一堆工作线程,你所做的只是让你的代码更加复杂。 现在你必须编写代码来pipe理它们。 如果你只是使用线程池,你可以免费获得所有的线程pipe理。 而且这个语言提供的线程池很可能会比你自己推出的任何东西更健壮,更有效率,更lessbug。
Thread t = new Thread(new ThreadStart(DoSomething)); t.Start(); t.Join();
我希望你通常会在Start()
和Join()
之间有一些额外的代码。 否则,额外的线程是无用的,你无故浪费资源。
人们太害怕线程使用的资源。 我从来没有见过创build和启动一个线程需要超过一毫秒。 您可以创build的线程数量没有硬性限制。 RAM使用率很小。 一旦你有几百个线程,由于上下文切换,CPU成为一个问题,所以在这一点上,你可能想要devise你的devise。
在现代硬件上,毫秒是很长的时间。 在3GHz的机器上这是300万个周期。 而且,你不是唯一创build线程的人。 你的线程和其他程序的线程竞争CPU。 如果你使用不太多的线程,另一个程序也是如此,那么你使用了太多的线程。
认真地说,不要让生活比需要的更复杂。 不要使用线程池,除非你需要一些非常具体的东西。
确实。 不要让生活更复杂。 如果你的程序需要多个工作线程,不要重新发明轮子。 使用线程池。 这就是为什么它在那里。 你会推出自己的string类吗?
只要你有工作者线程的概念,线程池就是有意义的。 任何时候,您都可以轻松地将处理分区为更小的作业,每个作业都可以独立处理,工作线程(因此也是线程池)是有意义的。
当你需要执行完全不相关和不相关的行为的线程时,线程池是没有意义的,这些行为不能被认为是“工作”。 例如,一个用于GUI事件处理的线程,另一个用于后端处理。 线程池在处理形成stream水线时也没有意义。
基本上,如果你有线程启动,处理一个工作,退出,一个线程池可能是要走的路。 否则,线程池是不是真的会帮助。
要争吵的答案,我会补充说,最好不要使用ThreadPool线程,如果你需要保证你的线程立即开始工作。 每个appdomain的线程池线程的最大数量是有限的,所以你的工作可能不得不等待,如果他们都忙。 毕竟它被称为“队列用户工作项目”。
当然有两个注意事项:
- 您可以在运行时更改代码中的线程池线程的最大数量,因此没有任何事情可以阻止您检查当前vs最大数目,并在必要时增加最大值。
- 转动一个新的线程有它自己的时间处罚 – 是否值得您采取冲击取决于您的情况。
我不是说在这里只有理论知识的人。 我编写和维护大量使用multithreading的应用程序,而且我通常不会发现线程池是正确的答案。
啊,来自权威的争论 – 但总是在寻找可能在Windows内核团队的人。
我们两个都没有争论的事实,如果你有一些具体的要求那么.NET ThreadPool可能不是正确的事情。 我们反对的是创造一个线程的机器成本的微不足道。
首先在ThreadPool上创build一个线程的重要开销。 我不希望我的机器被代码编写的代码误以为创build线程的代价,并且不知道它会导致在每个DLL中调用一个方法附加到进程(其中一些将由第三方创build),并且这可能使一些不需要在RAM中的代码加热,并且几乎肯定不需要在L1中。
现代机器中内存层次的形状意味着“分散”CPU是最糟糕的事情,所有关心自己工艺的人都应该努力工作以避免这种情况。
当你要执行一个需要很长时间的操作,或者是一个连续的后台线程。 我想你总是可以将池中可用的线程数量增加一些,但是对于一个永远不会回到池中的线程来说,pipe理成本是没有意义的。
MSDN有一个列表在这里的一些原因:
http://msdn.microsoft.com/en-us/library/0ka9477y.aspx
有几种scheme可以创build和pipe理自己的线程,而不是使用线程池线程:
- 你需要一个前台线程。
- 你需要一个线程有一个特定的优先级。
- 您有导致线程长时间阻塞的任务。 线程池具有最大数量的线程,因此大量阻塞的线程池线程可能会阻止任务启动。
- 您需要将线程放入单线程的公寓。 所有ThreadPool线程都在multithreading的公寓中。
- 您需要拥有与线程相关的稳定身份,或者将线程专用于任务。
线程池线程适用于满足以下两个条件的任务:
- 任务不需要花费任何时间等待发生
- 任何等待任务完成的任务都可能等待许多任务完成,所以它的调度优先级不会影响很多。
使用一个线程池线程而不是创build一个新线程将会节省大量但有限的时间。 如果与执行任务所花费的时间相比,这个时间显着,则线程池任务可能是合适的。 然而,执行任务所需的时间越长,使用线程池的好处就越小,并且妨碍线程池效率的任务的可能性也越大。
@Eric
@Derek,我并不完全同意你用这个例子。 如果您不确切知道机器上运行的是什么,以及在一定的负载下,您的应用程序将使用多less线程,句柄,CPU时间,RAM等,那么您将遇到麻烦。
你是你写的程序的唯一目标客户? 如果没有,你不能确定的大部分。 当你编写一个程序的时候,你一般都不知道它是否会有效的单独执行,或者它是否会在一个被DDOS攻击攻击的web服务器上运行。 你不知道你有多lessCPU时间。
假设程序的行为根据input而改变,甚至很less知道你的程序将消耗多less内存或CPU时间。 当然,你应该对你的程序的行为有一个很好的想法,但是绝大多数程序从来没有被分析过,以确定有多less内存,多less个句柄等等,因为完整的分析是很昂贵的。 如果你不写实时软件,那么付出是不值得的。
总的来说,声称完全知道你的程序行为如何是牵强的,并且声称对机器的一切都了如指掌。
说实话,如果你不知道你应该使用什么方法:手动线程,线程池,委托,以及如何实现它来做你的应用程序需要,你有麻烦。
我并不完全不同意,但我真的不知道这是如何相关的。 这个网站在这里具体是因为程序员并不总是有所有的答案。
如果您的应用程序足够复杂,需要调整您使用的线程数量,是不是几乎总是想要比框架给你更多的控制?
不,如果我需要一个线程池,我会使用提供的线程池,除非我发现这是不够的。 我不会简单地假设提供的线程池不足以满足我的需求,但没有确认情况。
我不是说在这里只有理论知识的人。 我编写和维护大量使用multithreading的应用程序,而且我通常不会发现线程池是正确的答案。
我的大部分专业经验都是multithreading和多处理程序。 我经常需要推出自己的解决scheme。 这并不意味着线程池不是很有用,或者在很多情况下是合适的。 线程池被构build来处理工作线程。 在多个工作线程合适的情况下,所提供的线程池通常应该是第一种方法。