.NET Real-Time和TaskMgr实时优先级类有什么区别?

时间:2019-01-05 16:06:41

标签: c# .net windows process

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

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

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

enter image description here

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

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

1 个答案:

答案 0 :(得分: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()清除本地存储的值。