【发布时间】:2010-11-06 17:01:15
【问题描述】:
我在 SO 上阅读随机问题和答案时遇到了这个问题:
C#, IAsyncResult and the thread pool
问题是X方法使用线程池还是使用普通线程。
使用线程池和普通线程有什么区别?
【问题讨论】:
标签: .net multithreading
我在 SO 上阅读随机问题和答案时遇到了这个问题:
C#, IAsyncResult and the thread pool
问题是X方法使用线程池还是使用普通线程。
使用线程池和普通线程有什么区别?
【问题讨论】:
标签: .net multithreading
线程池创建线程并将工作分配给空闲线程。这种为每个工作项创建和释放线程的方式是预防性的,因为创建和释放线程是一项相对昂贵的操作。
【讨论】:
ThreadPool 包含许多可供您使用的线程,这可能会消除创建新线程的成本,这就是您创建普通线程时发生的情况。
【讨论】:
线程池通常适用于短时间运行的任务。它的局限性在于它是一个应用程序范围的有限资源(每个 CPU 25 个),并且有很多内部类使用线程池,因此如果您执行大量长时间运行的任务,您将耗尽所有线程。
对于长时间运行的任务,最好使用手动创建的线程,并将其背景属性设置为 true。
注意:在 .NET Framework 2.0 版中,Thread.CurrentPrincipal 属性值传播到使用 QueueUserWorkItem 方法排队的工作线程。在早期版本中,不传播主体信息。
何时不使用线程池线程
有几种场景适合创建和管理自己的线程而不是使用线程池线程:
您需要一个前台线程(!)。
您需要线程具有特定的优先级。
您的任务会导致线程长时间阻塞。线程池具有最大线程数,因此大量阻塞的线程池线程可能会阻止任务启动。
您需要将线程放入单线程单元中。所有 ThreadPool 线程都在多线程单元中。
您需要有一个与线程相关联的稳定身份,或者将线程专用于某项任务。
一个很大的区别是线程池线程上未处理的异常会终止进程;除了这三个例外:
ThreadAbortException 被抛出到线程池线程中,因为调用了 Abort。
AppDomainUnloadedException 在线程池线程中被抛出,因为正在卸载应用程序域。
公共语言运行时或宿主进程终止线程。
一些很好的参考资料是:
Programming the Thread Pool in the .NET Framework
更新:响应 cmets。您可以使用GetAvailableThreads 方法来确定在任何给定时间线程池中的实际线程数。 ThreadPool.GetMaxThreads 是不同的数量。它是请求排队之前池中允许的最大值,而不是当前池中的实际线程数。
【讨论】:
不同之处不在于线程本身,因为它们的行为相同,不同之处在于谁管理线程的生命周期以及您如何使用它们。
.net 中的线程池是一个会增长或收缩的线程池,当您排队等待线程池处理时,它将决定是否需要启动新线程或重用现有线程。您不必显式创建线程。
这很好,但缺点是线程池中可用的线程数量有限,因此如果您将长时间运行的任务排队,这可能会对您的应用程序产生负面影响,因为您可能会用完线程池其他东西可能想要使用的线程。
看这个article关于线程池
【讨论】: