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

时间:2022-05-10 05:25:03

There are many places across the web and Stack Overflow where one is discouraged from changing the priority of a ThreadPool thread or TPL Task. In particular:

Web和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."

“你不应该改变PoolThread的文化或优先级......或者就像你不涂漆或重新装修租赁汽车一样。”

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

“ThreadPool中的每个线程都以默认优先级运行,而更改ThreadPriority的代码无效。”

However, it is a simple matter to do so, and the debugger shows that the change does seem to stick (insofar as the value can be read back).

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

Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;

So the question is, what is the specific reason for this particular taboo?

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

My suspicion: doing so disturbs the delicate load balancing-assumptions of the pool. But this doesn't explain why some sources say that you can't change it.

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

6 个解决方案

#1


20  

The thread pool, especially the .NET 4.0 thread pool, has many tricks up its sleeve and is a rather complicated system. Add in tasks and task schedulers and work stealing and all sorts of other things and the reality is you don't know what is going on. The thread pool may notice that your task is waiting on I/O and decide to schedule something quick on your task or suspend your thread to run something of higher priority. Your thread may somehow be a dependency for a higher-priority thread (that you may or may not be aware of) and end up causing a deadlock. Your thread may die in some abnormal way and be unable to restore priority.

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

If you have a long-running task such that you think it would be best that your thread have a lower priority then the thread pool probably isn't for you. While the algorithms have been improved in .NET 4.0, it is still best used for short-lived tasks where the cost of creating a new thread is disproportional to the length of the task. If your task runs for more than a second or two the cost of creating a new thread is insignificant (although management might be annoying).

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

#2


6  

I've done some experimentation with a reduced-size thread pool which seems to indicate that the thread's priority is reset back to normal once returned to the pool. This resource on threading seems to confirm it. So the effect seems to be very limited even if you do.

我已经完成了一个减小大小的线程池的实验,这似乎表明线程的优先级在返回池后重置为正常。这个关于线程的资源似乎证实了这一点。所以即使你这样做,效果似乎也非常有限。

#3


2  

Lowering the priority could also lead to unexpected consequences.

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

Imagine you schedule a task in an application, but also call into a library that schedules several other tasks. Say you lower the thread priority while the app task runs. You could then end up with the normal priority tasks in the lib waiting for that low priority task to finish, if the pool doesn't spawn many threads, but the low priority thread it may not be given much CPU time if the rest of the system has many normal priority threads that want to run.

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

Increasing the number of pool threads would alleviate this, at the cost of wasting more memory on stacks and spending more CPU time on context switches.

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

#4


1  

If you do change anything, use try/finally to make sure you leave it as you found it.

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

#5


0  

You certainly can change it if you really want to, but given that the thread pool threads are re-used, the next code that runs might not expect the change.

如果你真的想要,你当然可以改变它,但鉴于线程池线程被重用,下一个运行的代码可能不会期望更改。

#6


0  

It's discouraged, specially if you're upping the priority, because it can affect the overall performance of your system.

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

Not to offer an overcomplicated answer, but in general, thread priority is a complex topic. For example, Windows has 2 related descriptors: thread priority and process priority. Both range from Idle, the lowest, to Time critical, the highest. When you start a new process, it's set to the default, the mid-range (a normal process priority with a normal thread priority).

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

Plus, thread priorities are relative, meaning that even setting a thread's priority to the highest in a busy system won't ensure that it will run in 'real-time'. DotNET offers no guarantees on this, neither does Windows. From that you can see why it's better to leave the threadpool alone, since, 99.9% of the time, it knows best :)

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

All that said, it's ok to lower a thread's priority if the task involves a long computation. This won't affect other processes.

总而言之,如果任务涉及长时间计算,则可以降低线程的优先级。这不会影响其他进程。

Increasing priority, however, should only be done for tasks that need to react quickly, and have a short execution time, because this can negatively affect other processes.

但是,只应对需要快速响应并且执行时间短的任务执行优先级增加,因为这会对其他进程产生负面影响。

#1


20  

The thread pool, especially the .NET 4.0 thread pool, has many tricks up its sleeve and is a rather complicated system. Add in tasks and task schedulers and work stealing and all sorts of other things and the reality is you don't know what is going on. The thread pool may notice that your task is waiting on I/O and decide to schedule something quick on your task or suspend your thread to run something of higher priority. Your thread may somehow be a dependency for a higher-priority thread (that you may or may not be aware of) and end up causing a deadlock. Your thread may die in some abnormal way and be unable to restore priority.

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

If you have a long-running task such that you think it would be best that your thread have a lower priority then the thread pool probably isn't for you. While the algorithms have been improved in .NET 4.0, it is still best used for short-lived tasks where the cost of creating a new thread is disproportional to the length of the task. If your task runs for more than a second or two the cost of creating a new thread is insignificant (although management might be annoying).

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

#2


6  

I've done some experimentation with a reduced-size thread pool which seems to indicate that the thread's priority is reset back to normal once returned to the pool. This resource on threading seems to confirm it. So the effect seems to be very limited even if you do.

我已经完成了一个减小大小的线程池的实验,这似乎表明线程的优先级在返回池后重置为正常。这个关于线程的资源似乎证实了这一点。所以即使你这样做,效果似乎也非常有限。

#3


2  

Lowering the priority could also lead to unexpected consequences.

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

Imagine you schedule a task in an application, but also call into a library that schedules several other tasks. Say you lower the thread priority while the app task runs. You could then end up with the normal priority tasks in the lib waiting for that low priority task to finish, if the pool doesn't spawn many threads, but the low priority thread it may not be given much CPU time if the rest of the system has many normal priority threads that want to run.

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

Increasing the number of pool threads would alleviate this, at the cost of wasting more memory on stacks and spending more CPU time on context switches.

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

#4


1  

If you do change anything, use try/finally to make sure you leave it as you found it.

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

#5


0  

You certainly can change it if you really want to, but given that the thread pool threads are re-used, the next code that runs might not expect the change.

如果你真的想要,你当然可以改变它,但鉴于线程池线程被重用,下一个运行的代码可能不会期望更改。

#6


0  

It's discouraged, specially if you're upping the priority, because it can affect the overall performance of your system.

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

Not to offer an overcomplicated answer, but in general, thread priority is a complex topic. For example, Windows has 2 related descriptors: thread priority and process priority. Both range from Idle, the lowest, to Time critical, the highest. When you start a new process, it's set to the default, the mid-range (a normal process priority with a normal thread priority).

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

Plus, thread priorities are relative, meaning that even setting a thread's priority to the highest in a busy system won't ensure that it will run in 'real-time'. DotNET offers no guarantees on this, neither does Windows. From that you can see why it's better to leave the threadpool alone, since, 99.9% of the time, it knows best :)

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

All that said, it's ok to lower a thread's priority if the task involves a long computation. This won't affect other processes.

总而言之,如果任务涉及长时间计算,则可以降低线程的优先级。这不会影响其他进程。

Increasing priority, however, should only be done for tasks that need to react quickly, and have a short execution time, because this can negatively affect other processes.

但是,只应对需要快速响应并且执行时间短的任务执行优先级增加,因为这会对其他进程产生负面影响。