4

我已经编写了一些(c# 3.5)批处理代码,可以选择覆盖线程池 maxthreads。它使用了一些非线程安全的相当重的资源,需要为每个活动线程维护一个“资源池”并使用一个项目。消费应用程序可以设置批处理器将使用多少线程的限制,这反过来又调用ThreadPool.SetMaxThreads(). 我这样做是为了测试手动设置限制是否比保留默认设置具有更好的性能。

我的问题是,每次使用批处理代码后,我是否应该将 maxthreads 重置回应用程序的先前值?它会在一天中间歇性地被调用,可能会被调用数千次。MaxThreads 限制会一直持续到应用程序重新启动/设置为不同的值,还是会自动重置?

虽然这在我的测试工具中并不是一个真正的问题,但我想知道我是否应该更新代码以在批处理完成后处理其他资源以在生产环境中使用时“重置”线程池。仅将其覆盖是否有任何影响?

最后,在一个 .net 应用程序中设置线程池是为盒子上的所有应用程序设置它,还是只为该单个应用程序的上下文设置它?

4

3 回答 3

3

TL;DR:不要使用SetMaxThreads.

此设置是针对每个进程的:其他进程不受影响,但您的整个应用程序会受影响!这被称为“局部问题的全局解决方案”,被认为是一件坏事。

您只希望应用程序的某些部分受此设置影响,但您正在影响整个应用程序。

例如,如果您将 max-threads 设置为较低的值以限制并发性,您将耗尽整个应用程序的其余部分,包括 ASP.NET 请求线程等。

出于这个原因,我总是更喜欢在本地解决这些问题。许多 TPL 原语(PLINQ、Parallel.*)允许您设置最大并行度。对于简单的任务,您可以使用具有固定线程数的自定义任务调度程序(ParallelExtras 中提供代码)。

于 2012-08-24T10:51:37.990 回答
1

如果您降低级别,线程池将杀死线程,这将(GoodThing™)减少内存使用(所有这些线程的堆栈),并且(BadThing™)意味着当您再次提升级别时必须再次创建它们. 如果同时有大量使用线程池的任务(BadThing™),它也可能使池过于慷慨,尽管很可能有足够多的任务阻塞,池的整体使用实际上更好(GoodThing™ )。不过,有可能它在那个时期的使用量太低而无法产生影响(嗯,IrrelevantThing™)。

总而言之,我可能只是将池设置为在应用程序启动时的繁忙时段所需的最高值,然后不理会它。如果在应用程序的其余运行期间存在性能问题,则在其他期间降低级别值得尝试,但除非在这些期间内存或线程使用是一个问题,否则我不会,因为这些线程将被使用毕竟在未来再次。只设置一次关卡更简单,而且更简单总是更好,除非你能解释为什么不设置(“尽可能简单,但不简单”)。

编辑:

我将以上内容作为对该问题的直接回答而写,但其他建议根本不触及最大线程的答案确实很划算。如果您真的非常需要大量线程,请自己创建它们(或者不要池化,或者自己处理池化,这取决于启动时间的重要性)。但在此之前,请考虑替代方案,因为它在很多时候也不是最好的方法。

于 2012-08-24T10:23:29.870 回答
1

首先,正如 msdn 所说:

“更改线程池中的最大线程数时要小心。虽然您的代码可能会受益,但更改可能会对您使用的代码库产生不利影响。

将线程池大小设置得太大会导致性能问题。如果同时执行的线程太多,任务切换开销就会成为一个重要因素。”

使用托管解决方案,线程可以由 IIS 控制(可能限制甚至防止被更改),具体取决于哪个版本的 IIS,这可以应用于盒子上的所有应用程序,或者如果它们的继承设置被更改,则应用于单个应用程序。

PS 有关更多信息,请参阅此类似帖子,并查看线程池节流链接以获得有趣的阅读点击我!

于 2012-08-24T10:40:31.853 回答