【问题标题】:What's the difference between .NET Real-Time and TaskMgr Real-time priority class?.NET Real-Time 和 TaskMgr 实时优先级类有什么区别?
【发布时间】:2019-01-05 16:06:41
【问题描述】:

当我在 .NET 中将进程的优先级设置为实时时:

Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;

它在任务管理器中仅显示为“高”优先级:

如果我在任务管理器中手动将其设置为实时,然后再次执行Process.GetCurrentProcess(),ProcessPriorityClass 仍会报告为ProcessPriorityClass.RealTime。

如果我以管理员身份运行应用程序,则优先级会更改为实时,正如任务管理器所报告的那样。所以看起来,当以普通用户身份运行时,您可以将其设置为 RealTime,它会被 .NET 报告为这样,但该进程的实际优先级实际上只是 High。为什么在这种情况下 .NET 和 TaskManager 会报告不同的值?

【问题讨论】:

  • 也许使用 ILSpy 会有所帮助。

标签: c# .net windows process


【解决方案1】:

真正的罪魁祸首是 Windows。

setter of the PriorityClass property 很简单:

 set {
        if (!Enum.IsDefined(typeof(ProcessPriorityClass), value)) { 
            throw new InvalidEnumArgumentException("value", (int)value, typeof(ProcessPriorityClass));
        }

        // BelowNormal and AboveNormal are only available on Win2k and greater.
        if (((value & (ProcessPriorityClass.BelowNormal | ProcessPriorityClass.AboveNormal)) != 0)   && 
            (OperatingSystem.Platform != PlatformID.Win32NT || OperatingSystem.Version.Major < 5)) {
            throw new PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported), null);
        }                

        SafeProcessHandle handle = null;

        try {
            handle = GetProcessHandle(NativeMethods.PROCESS_SET_INFORMATION);
            if (!NativeMethods.SetPriorityClass(handle, (int)value)) {
                throw new Win32Exception();
            }
            priorityClass = value;
            havePriorityClass = true;
        }
        finally {
            ReleaseProcessHandle(handle);
        }
    }

经过几次健全性检查后,它会调用 Windows API SetPriorityClass,然后检查返回码。如果发生错误,它会抛出异常。否则,它会在本地存储新优先级的值(这样,当您读取 PriorityClass 的值时,它就不必回叫 Windows 来检查它)。

在某些情况下,Windows 会拒绝更改优先级(例如,正如您所注意到的,您现在需要管理员权限来设置实时优先级)。诀窍是 Windows 默默地拒绝优先级更改并且不返回错误代码。如记录的here:

请注意,即使优先级未设置为 REALTIME_PRIORITY_CLASS,对 SetPriorityClass() 的调用也可能返回成功,因为如果您没有“增加调度优先级”权限,则对 REALTIME_PRIORITY_CLASS 的请求将被解释为对最高优先级的请求当前帐户中允许的类。

我猜这样做是为了避免破坏不希望调用失败的遗留应用程序。因此,您的 .NET 应用程序不知道优先级更改未按预期工作,并返回错误值。


也就是说,即使 Windows 确实按预期设置了优先级,.NET 代码在某些情况下仍然无法工作。例如,假设您将PriorityClass 设置为BelowNormal。如上所述,该值将本地存储在 Process 对象中。然后,如果您再次更改优先级但从任务管理器中更改,就像以前一样,.NET 不会意识到它并返回旧值。

如果您绝对需要最新信息,请先致电process.Refresh() 清除本地存储的值。

【讨论】:

  • process.PriorityClass = ProcessPriorityClass.RealTime; Console.WriteLine($"Priority class cached: {process.PriorityClass}"); process.Refresh(); Console.WriteLine($"Actual priority class: {process.PriorityClass}"); 在没有管理员权限的情况下运行,打印:Priority class assumed: RealTime Actual priority class: High 没错,问题在于 Process 类缓存了一个假定值,而不是从 Windows 获取它。
猜你喜欢
  • 2010-09-09
  • 2014-06-11
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 2022-01-26
相关资源
最近更新 更多