为什么*不*改变ThreadPool(或任务)线程的优先级?

时间:2011-04-08 01:09:51

标签: .net task-parallel-library task threadpool thread-priority

网络和Stack Overflow中有很多地方不鼓励人们更改 ThreadPool 主题或TPL 任务的优先级。特别是:

"You have no control over the state and priority of a thread pool thread."
"The runtime manages the thread pool. You have no control over the scheduling of the thread, nor can you change the thread's priority."

"You should not change the Culture or Priority or... of a PoolThread. Just like you don't paint or re-decorate a rental car."

"There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads: (such as...) You require a thread to have a particular priority."

"Each thread in ThreadPool runs at the default priority and the code to change the ThreadPriority has no effect."

但是,这样做很简单,并且调试器显示更改 似乎仍然存在(只要可以回读该值)。

Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;

所以问题是,这个特定禁忌的具体原因是什么?

我的怀疑:这样做会扰乱游泳池的微妙负载平衡假设。但这并不能解释为什么有些消息来源说你不能改变它。

6 个答案:

答案 0 :(得分:21)

线程池,特别是.NET 4.0线程池,有许多技巧,是一个相当复杂的系统。添加任务和任务调度程序以及工作窃取和各种其他事情,现实是你不知道发生了什么。线程池可能会注意到您的任务正在等待I / O并决定快速安排任务,或者暂停线程以运行更高优先级的事务。您的线程可能以某种方式成为优先级较高的线程(您可能或可能不知道)的依赖项,并最终导致死锁。您的线程可能会以某种异常方式死亡,无法恢复优先级。

如果你有一个长期运行的任务,你认为你的线程最好具有较低的优先级,那么线程池可能不适合你。虽然.NET 4.0中的算法得到了改进,但它仍然最适合用于创建新线程的成本与任务长度不成比例的短期任务。如果您的任务运行超过一两秒,则创建新线程的成本微不足道(尽管管理可能很烦人)。

答案 1 :(得分:8)

我已经对缩小大小的线程池做了一些实验,这似乎表明线程的优先级在返回池后重置为正常。线程上的This资源似乎证实了这一点。因此,即使你这样做,效果似乎也非常有限。

答案 2 :(得分:2)

降低优先级也可能导致意外后果。

想象一下,您在应用程序中安排任务,但也调用了一个安排其他几个任务的库。假设您在应用任务运行时降低线程优先级。然后你可以在lib中等待那个低优先级任务完成的正常优先级任务,如果池没有产生很多线程,但是低优先级线程如果剩下的那个则可能没有给它太多的CPU时间。系统有许多想要运行的普通优先级线程。

增加池线程数可以缓解这种情况,代价是在堆栈上浪费更多内存并在上下文切换上花费更多CPU时间。

答案 3 :(得分:0)

如果你真的想要,你肯定可以改变它,但是考虑到线程池线程被重用,下一个运行的代码可能不会发生变化。

答案 4 :(得分:0)

如果您确实更改了任何内容,请使用try / finally确保在找到它时保留它。

答案 5 :(得分:0)

不鼓励,特别是如果你提高优先级,因为它会影响你系统的整体性能。

不提供过于复杂的答案,但一般来说,线程优先级是一个复杂的主题。例如,Windows有2个相关的描述符:线程优先级和进程优先级。两者的范围从空闲,最低,到时间关键,最高。当您启动新进程时,它将设置为默认值,即中间范围(具有正常线程优先级的正常进程优先级)。

另外,线程优先级是相对的,这意味着即使在繁忙的系统中将线程的优先级设置为最高也不会确保它将“实时”运行。 DotNET不提供此保证,Windows也不提供保证。从那里你可以看出为什么最好不要单独留下线程池,因为,99.9%的时间,它最了解:)

所有这一切,如果任务涉及长计算,则可以降低线程的优先级。这不会影响其他进程。

然而,只有那些需要快速反应并且执行时间短的任务才能提高优先级,因为这会对其他进程产生负面影响。