C# 什么';.NET实时和TaskMgr实时优先级类之间的区别是什么?
在.NET中将进程的优先级类设置为实时时:C# 什么';.NET实时和TaskMgr实时优先级类之间的区别是什么?,c#,.net,windows,process,C#,.net,Windows,Process,在.NET中将进程的优先级类设置为实时时: Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; 它在任务管理器中仅显示为“高”优先级: 如果我在任务管理器中将其手动设置为实时,然后再次执行Process.GetCurrentProcess(),则ProcessPriorityClass仍报告为ProcessPriorityClass.RealTime 如果我以管理员的身份运行该应用程序,那么优先
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 APISetPriorityClass
,然后检查返回代码。如果发生错误,它将抛出异常。否则,它会在本地存储新优先级的值(这样,当您读取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获取。