C# 什么';.NET实时和TaskMgr实时优先级类之间的区别是什么?

C# 什么';.NET实时和TaskMgr实时优先级类之间的区别是什么?,c#,.net,windows,process,C#,.net,Windows,Process,在.NET中将进程的优先级类设置为实时时: Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; 它在任务管理器中仅显示为“高”优先级: 如果我在任务管理器中将其手动设置为实时,然后再次执行Process.GetCurrentProcess(),则ProcessPriorityClass仍报告为ProcessPriorityClass.RealTime 如果我以管理员的身份运行该应用程序,那么优先

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

Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
它在任务管理器中仅显示为“高”优先级:

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


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

真正的罪魁祸首是Windows

问题很简单:

 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);
        }
    }
set{
如果(!Enum.IsDefined(typeof(ProcessPriorityClass),value)){
抛出新的InvalidEnumArgumentException(“值”,(int)值,typeof(ProcessPriorityClass));
}
//低于正常值和高于正常值仅在Win2k及更高版本上可用。
如果((值和(ProcessPriorityClass.BelowNormal | ProcessPriorityClass.Overnormal))!=0)和
(OperatingSystem.Platform!=PlatformID.Win32NT | | OperatingSystem.Version.Major<5)){
抛出新的PlatformNotSupportedException(SR.GetString(SR.PriorityClassNotSupported),null);
}                
SafeProcessHandle=null;
试一试{
handle=GetProcessHandle(NativeMethods.PROCESS\u SET\u信息);
if(!NativeMethods.SetPriorityClass(句柄,(int)值)){
抛出新的Win32Exception();
}
优先级类=值;
havePriorityClass=true;
}
最后{
释放进程句柄(句柄);
}
}
经过几次健全性检查后,它调用Windows API
SetPriorityClass
,然后检查返回代码。如果发生错误,它将抛出异常。否则,它会在本地存储新优先级的值(这样,当您读取
PriorityClass
的值时,它就不必调用Windows来检查它)

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

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

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


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


如果您确实需要最新信息,请首先调用
process.Refresh()
清除本地存储的值。

使用ILSpy可能会有所帮助。
process.PriorityClass=ProcessPriorityClass.RealTime;WriteLine($“缓存的优先级类:{process.PriorityClass}”);process.Refresh();WriteLine($“实际优先级类:{process.PriorityClass}”)在没有管理员权限的情况下运行时,打印:
假定优先级等级:实时实际优先级等级:高
,没错,问题是Process类缓存假定值,而不是从Windows获取。