进程优先级和线程池优先级之间是否存在关联(C#)

4

我知道不能在运行过程中更改线程池优先级,但是在线程池中运行的特定任务的优先级是否与调用进程的优先级有关呢?

换句话说,无论调用进程的优先级如何,线程池中的所有任务是否都以相同的优先级运行?

谢谢。

更新1:我应该更加具体,我指的是 Parallel.ForEach 中的线程。


进程不能使用彼此的线程池,我猜你的意思是进程等于线程。 - H H
3个回答

5
我知道线程池的优先级不应该/不能被运行的进程更改。
这并不完全正确。您可以更改线程池的线程优先级(在委托内部),它将以新的优先级运行,但默认值将在其任务完成时恢复,并发送回池中。
ThreadPool.QueueUserWorkItem(delegate(object state) {
    Thread.CurrentThread.Priority = ThreadPriority.Highest;

    // Code in this function will run with Highest priority
});

“线程池中运行的特定任务的优先级是否与调用进程的优先级有关?”是的,它不仅适用于线程池中的线程。在Windows中,进程的优先级由其类别确定(从IDLE_PRIORITY_CLASS到REALTIME_PRIORITY_CLASS)。与线程的优先级(从THREAD_PRIORITY_IDLE到THREAD_PRIORITY_TIME_CRITICAL)一起使用,将用于计算线程的最终优先级。
来自MSDN的说明:
“进程优先级类和线程优先级级别相结合,形成每个线程的基本优先级。”
请注意,这不仅仅是基本优先级加上偏移量:
NORMAL_PRIORITY_CLASS + THREAD_PRIORITY_IDLE  == 1
NORMAL_PRIORITY_CLASS + THREAD_PRIORITY_TIME_CRITICAL == 15

但是:
REALTIME_PRIORITY_CLASS + THREAD_PRIORITY_IDLE == 16
REALTIME_PRIORITY_CLASS + THREAD_PRIORITY_TIME_CRITICAL == 31

此外,线程可以拥有临时的“提升”(由Windows Scheduler决定和管理)。请注意,进程也可以更改自己的优先级类别。
换句话说,线程池中的所有任务是否以相同的优先级运行,而不考虑调用进程的优先级?
不,线程的优先级取决于进程的优先级(参见上一段),池中的每个线程都可以暂时具有不同的优先级。还要注意,线程优先级不受调用线程优先级的影响:
ThreadPool.QueueUserWorkItem(delegate(object s1) {
    Thread.CurrentThread.Priority = ThreadPriority.Highest;

    ThreadPool.QueueUserWorkItem(delegate(object s2) {
        // This code is executed with ThreadPriority.Normal

        Thread.CurrentThread.Priority = ThreadPriority.Lowest;

        // This code is executed with ThreadPriority.Lowest
    });

    // This code is executed with ThreadPriority.Highest
});

编辑: .NET任务使用线程池,因此仍适用于上述内容。例如,如果您正在使用Parallel.ForEach枚举集合以增加线程优先级,则必须在循环内部执行此操作:

Parallel.ForEach(items, item => {
    Thread.CurrentThread.Priority = ThreadPriority.Highest;

    // Your code here...
});

注意:更改优先级时要小心。例如,如果两个线程使用共享资源(由锁保护),则存在许多竞争来获取该资源,其中一个具有最高优先级,然后您可能会得到非常高的CPU使用率(由于 Monitor.Enter自旋行为)。这只是一个问题,请参阅MSDN了解更多细节(增加线程的优先级甚至可能导致性能更差)。


1

线程池中的所有任务是否以相同的优先级运行,而不考虑调用进程的优先级?

必须如此。在池中丢弃的唯一内容是委托。它保存对对象的引用,但不保存将其丢弃的线程的引用。


0

目前正在运行的线程具有相同的优先级。但是对于尚未运行的线程,存在一个队列 - 因此实际上存在“优先级”。更令人困惑的是,操作系统可以提高(和限制)线程优先级,例如当线程池中的两个线程彼此依赖时(例如,一个线程阻塞另一个线程)。当然,每当某些东西在线程池上阻塞时,您就会浪费资源:D

话虽如此,您真的不应该改变线程优先级,无论是否使用线程池。您真的不需要这样做,而且线程(和进程)优先级的工作方式可能与您预期的不同 - 这根本不值得。将所有内容保持正常状态,只需忽略存在Priority属性即可避免许多不必要的问题 :)

在互联网上可以找到很多好的解释 - 例如,http://blog.codinghorror.com/thread-priorities-are-evil/。当然,这些通常已经过时了 - 但线程优先级的概念也是如此 - 它们是为单核机器设计的,在操作系统并不擅长抢占式多任务处理的时代。


谢谢。但是,如果我的作业在100%的CPU下运行超过1小时,我必须有另一个不必要的更大问题:> - DayDayHappy
@DayDayHappy 是的,通常是这样。分析器可以帮助您确定 - 我曾经看到过一些代码片段,它们花费了很长时间,同时占用了100%的CPU,只是因为多线程不佳。话虽如此,如果消耗是自然的,那么100%的CPU使用率就没有什么问题 - 现代操作系统和CPU通常可以在不损害整个系统性能的情况下处理它。如果您真的想要,您总是可以添加限制,但实际上并不需要。线程优先级更可能会造成伤害而不是帮助 - 调度程序在每个人都是正常状态时运行得最好:D - Luaan
我的习惯是将进程优先级降低到最低,因为我知道我的任务需要长时间运行,可能会意外地运行更长时间,所以我想给其他任务让路。谢谢。 - DayDayHappy
@DayDayHappy 是的,我完全理解 - 在 Windows 3.1(以及在较小程度上是 95 系列)时代,这曾经是一种非常好的防御性编码方式。但在 NT 上并没有什么用处。有趣的是,即使在那个时候,它大多数情况下也是有用的,因为其他应用程序编写不正确(包括错误地管理其线程/进程优先级)。实际上,这就是首次添加抢占式多线程的原因之一 - 防止糟糕编写的应用程序杀死/冻结整个系统:D - Luaan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接