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

时间:2008-08-13 19:24:22

标签: c# .net multithreading design-decisions

我应该何时使用.Net中的ThreadPool?

看起来最好的选择是使用ThreadPool,在这种情况下,为什么它不是唯一的选择?

你对此有什么看法?

9 个答案:

答案 0 :(得分:29)

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

  

我更喜欢手动创建我的线程并自己控制它们。它使代码非常容易理解。

在适当的时候这很好。但是,如果您需要一堆工作线程,那么您所做的就是让代码更复杂。现在你必须编写代码来管理它们。如果您刚刚使用了线程池,那么您将免费获得所有线程管理。而且语言提供的线程池很可能比你为自己滚动的更强大,更高效,更少错误。

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

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

  

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

现代硬件上的毫秒是时间。这是3GHz机器上的300万次循环。而且,你不是唯一一个创建线程的人。您的线程与每个其他程序的线程竞争CPU。如果你使用的线程不是太多,那么另一个程序也是如此,那么你就会使用过多的线程。

  

说真的,不要让生活变得更加复杂。除非你需要一些非常具体的东西,否则不要使用线程池。

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

答案 1 :(得分:17)

我不会使用ThreadPool进行廉价多线程的唯一原因是我需要......

  1. 与正在运行的方法相互作用(例如,杀死它)
  2. STA thread上运行代码(这发生在我身上)
  3. 在我的应用程序死亡后保持线程活动(ThreadPool线程是后台线程)
  4. 以防我需要更改Thread的优先级。我们无法在ThreadPool中更改线程的优先级,默认情况下为Normal。
  5.   

    PS: MSDN文章"The Managed Thread Pool"包含标题为“何时不使用线程池线程”的部分,其中包含非常相似但略微更完整的内容不使用线程池的可能原因列表。

    您需要跳过ThreadPool的原因有很多,但如果您不了解它们,那么ThreadPool应该足够好了。

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

答案 2 :(得分:8)

只要拥有工作线程的概念,线程池就有意义。任何时候您都可以轻松地将处理分区为较小的作业,每个作业都可以独立处理,工作线程(以及线程池)是有意义的。

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

基本上,如果您有启动,处理作业和退出的线程,则可能是一种线程池。否则,线程池实际上并没有帮助。

答案 3 :(得分:8)

对于quarrelsome的回答,我想补充一点,如果你需要保证你的线程会立即开始工作,最好不要使用ThreadPool线程。每个appdomain限制运行的线程池线程的最大数量,因此如果它们都忙,您的工作可能需要等待。毕竟,它被称为“队列用户工作项”。

当然有两点需要注意:

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

答案 4 :(得分:2)

  

我不是只和别人说话   理论知识在这里。我写   并维护大批量应用程序   大量使用多线程,   我一般都找不到线程   游泳池是正确的答案。

啊,来自权威的争论 - 但总是关注那些可能在Windows内核团队中的人。

我们都没有争辩说如果你有一些特定的要求那么.NET ThreadPool可能不是正确的。我们反对的是创建线程的机器成本的微不足道。

首先在ThreadPool的创作点上创建一个线程的巨大费用。我不希望我的机器充满了被误导创建线程费用的人编写的代码,例如,我不知道它会导致在每个DLL中调用一个方法,这是附加到进程(其中一些将由第三方创建),并且可能很好地加热一些代码,这些代码根本不需要在RAM中,几乎肯定不需要在L1中。

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

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

  1. 任务不必花费任何重要时间等待事情发生
  2. 等待任务完成的任何事情都可能等待许多任务完成,因此其调度优先级不会对事情造成太大影响。

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

答案 7 :(得分:0)

MSDN列出了一些原因:

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

  

有几种情况适合创建和   管理自己的线程而不是使用线程池线程:

     
      
  • 您需要一个前台线程。
  •   
  • 您需要一个具有特定优先级的线程。
  •   
  • 您的任务导致线程长时间阻塞。线程池有最大线程数,所以很大   被阻止的线程池线程数可能会阻止任务   开始。
  •   
  • 您需要将线程放入单线程单元中。所有ThreadPool线程都在多线程单元中。
  •   
  • 您需要具有与该线程关联的稳定标识,或者将线程专用于任务。
  •   

答案 8 :(得分:-1)

@Eric

  

@Derek,我不完全同意你用作例子的场景。如果您不确切地知道您的计算机上正在运行的是什么以及您的应用程序在一定负载下将使用的总线程数,句柄数,CPU时间数,RAM数等,那么您就遇到了麻烦。

您是您编写的计划的唯一目标客户吗?如果没有,你无法确定大部分内容。您通常不知道何时编写程序是否会有效执行,或者它是否会在受DDOS攻击打击的Web服务器上运行。你不知道你将有多少CPU时间。

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

一般来说,声称要确切知道你的程序将如何表现是不了解的,并声称知道有关机器的一切都是荒谬的。

  

说实话,如果您不确切知道应该使用哪种方法:手动线程,线程池,委托以及如何实现它以满足您的应用程序需求,那么您就遇到了麻烦。

我并不完全不同意,但我真的不明白这是如何相关的。这个网站特别是因为程序员并不总是有所有的答案。

  

如果您的应用程序足够复杂,需要限制您使用的线程数,那么您是否几乎总是希望获得比框架提供的更多控制权?

没有。如果我需要一个线程池,我将使用所提供的线程池,除非并且直到我发现它是不够的。我不会简单地假设提供的线程池不足以满足我的需要而不确认是这种情况。

  

我不是说这里只有理论知识的人。我编写和维护大量使用多线程的高容量应用程序,我通常不会发现线程池是正确的答案。

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