关于c#:何时不应该在.Net中使用ThreadPool?

关于c#:何时不应该在.Net中使用ThreadPool?

When should I not use the ThreadPool in .Net?

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

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

您对此有何经验?


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

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

适当的时候很好。但是,如果您需要一堆工作线程,那么您要做的就是使代码更复杂。现在,您必须编写代码来管理它们。如果您仅使用了线程池,则将免费获得所有线程管理。而且,与您自己编写的内容相比,该语言提供的线程池很可能更健壮,更有效且错误更少。

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

我希望您通常在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.

在现代硬件上,毫秒级时间很长。在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.

确实。不要让生活变得更复杂。如果您的程序需要多个工作线程,请不要浪费时间。使用线程池。这就是为什么它在那里。您会滚动自己的字符串类吗?


我不使用ThreadPool进行廉价多线程处理的唯一原因是,如果我需要

  • 与正在运行的方法进行交互(例如杀死它)
  • 在STA线程上运行代码(这发生在我身上)
  • 在我的应用程序终止后使线程保持活动状态(ThreadPool线程是后台线程)
  • 万一我需要更改线程的优先级。我们无法在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.

    有很多原因导致您需要跳过ThreadPool,但是如果您不知道它们,那么ThreadPool应该足够适合您。

    另外,请查看新的Parallel Extensions Framework,该框架中包含一些精巧的东西,可以满足您的需求,而不必使用ThreadPool


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

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

    基本上,如果您有启动,处理作业并退出的线程,则可能要使用线程池。否则,线程池并没有真正的帮助。


    为了解决这个问题,我要补充一点,如果您需要确保您的线程将立即开始工作,那么最好不要使用ThreadPool线程。每个应用程序域中正在运行的线程池化线程的最大数量受到限制,因此,如果它们都很忙,您的工作可能需要等待。毕竟,它被称为"队列用户工作项"。

    当然,有两个警告:

  • 您可以在运行时更改代码中线程池化线程的最大数量,因此没有什么可以阻止您检查当前数量与最大数量以及在需要时增加最大数量。
  • 旋转一个新线程会带来自己的时间损失-是否值得一试,取决于您的情况。

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

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

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

    首先,在ThreadPool的存在理由上创建线程会产生大量开销。我不希望我的机器充满由错误地了解创建线程的开销的人编写的代码,例如,不知道它会导致在每个单独的DLL中调用一个方法。附加到进程中(其中一些将由第三方创建),并且很可能会加重根本不需要在RAM中并且几乎肯定不需要在L1中的代码负载。

    现代计算机中内存层次结构的形状意味着"分散" CPU是您可能会做的最坏的事情,每个关心自己工艺的人都应该努力避免它。


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


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

  • 该任务将不必花费大量时间等待发生的事情

  • 等待任务完成的任何事情都可能会等待许多任务完成,因此其调度优先级不会对事情产生太大影响。

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


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

    http://msdn.microsoft.com/zh-CN/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.

    埃里克

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

    您是编写程序的唯一目标客户吗?如果不是,您将无法确定大多数情况。通常,您在编写程序时不知道它是否可以有效地单独执行,还是可以在受到DDOS攻击的Web服务器上运行。您不知道要使用多少CPU时间。

    假设程序的行为基于输入而变化,那么很少知道确切的程序消耗多少内存或CPU时间。当然,您应该对程序的行为有一个很好的了解,但是绝不会对大多数程序进行分析来确定要使用多少内存,多少句柄等,因为全面的分析非常昂贵。如果您不编写实时软件,那么付出的代价就不值得了。

    通常,声称确切了解您的程序将如何运行是一件很困难的事,并且声称了解有关计算机的所有信息都非常荒谬。

    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.

    我并不完全不同意,但是我真的看不出这有什么关系。该站点专门用于此处,因为程序员并非始终都能获得所有答案。

    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?

    不需要。如果我需要一个线程池,我将使用提供的线程池,除非直到发现它不够用为止。我不会简单地假设所提供的线程池不足以满足我的需求,而无需确认情况是否如此。

    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.

    我的大部分专业经验是关于多线程和多处理程序的。我经常也需要推出自己的解决方案。这并不意味着线程池是无用的,或者在许多情况下是适当的。建立线程池是为了处理工作线程。在适合使用多个工作线程的情况下,通常应首先使用提供的线程池。


  • 推荐阅读