简体   繁体   English

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

[英]What's the difference between .NET Real-Time and TaskMgr Real-time priority class?

When I set a process' priority class to real-time in .NET:当我在 .NET 中将进程的优先级设置为实时时:

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

It appears only as "High" priority in Task Manager:它仅在任务管理器中显示为“高”优先级:

在此处输入图片说明

If I manually set it to Real time in Task Manager and then do Process.GetCurrentProcess() again, the ProcessPriorityClass is still reported as ProcessPriorityClass.RealTime .如果我在任务管理器中手动将其设置为实时,然后再次执行Process.GetCurrentProcess() ,则ProcessPriorityClass仍报告为ProcessPriorityClass.RealTime

If I run the app as admin, then the priority class does change to Real time, as reported by Task Manager.如果我以管理员身份运行应用程序,则优先级类确实会更改为实时,如任务管理器所报告的那样。 So it appears that when running as a normal user, you can set it to RealTime and it will be reported as such by .NET, but the actual priority of the process is actually just High.所以看起来,当以普通用户身份运行时,您可以将其设置为RealTime,它会被.NET报告为这样,但该进程的实际优先级实际上只是High。 Why do .NET and TaskManager report different values in this case?为什么 .NET 和 TaskManager 在这种情况下报告不同的值?

The real culprit here is Windows.真正的罪魁祸首是 Windows。

The setter of the PriorityClass property is straightforward: PriorityClass属性setter很简单:

 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);
        }
    }

After a few sanity checks, it calls the Windows API SetPriorityClass , then it checks the return code.经过几次健全性检查后,它调用 Windows API SetPriorityClass ,然后检查返回代码。 If an error occurs, it throws an exception.如果发生错误,则抛出异常。 Otherwise, it stores locally the value of the new priority (so that, when you read the value of PriorityClass , it doesn't have to call Windows back to check it).否则,它会在本地存储新优先级的值(这样,当您读取PriorityClass的值时,它就不必回调 Windows 来检查它)。

In some conditions, Windows will deny the change of priority (for instance, as you noticed, you now need administrator privileges to set the real-time priority).在某些情况下,Windows 会拒绝更改优先级(例如,如您所见,您现在需要管理员权限来设置实时优先级)。 The trick is that Windows denies the priority change silently and does not return an error code .诀窍是 Windows以静默方式拒绝优先级更改并且不返回错误代码 As documented here :如此处所述

Note that the call to SetPriorityClass() may return success even though the priority was not set to REALTIME_PRIORITY_CLASS, because if you don't have the Increase Scheduling Priority permission, a request for REALTIME_PRIORITY_CLASS is interpreted as a request for the highest priority class allowed in the current account.请注意,即使优先级未设置为 REALTIME_PRIORITY_CLASS,对 SetPriorityClass() 的调用也可能返回成功,因为如果您没有增加调度优先级权限,则对 REALTIME_PRIORITY_CLASS 的请求将被解释为对允许的最高优先级类的请求当前帐户。

I'm guessing this is done to avoid breaking legacy applications that wouldn't expect their call to fail.我猜这样做是为了避免破坏不希望调用失败的遗留应用程序。 Because of this, your .NET application is not aware that the priority change didn't work as expected, and returns the wrong value.因此,您的 .NET 应用程序不知道优先级更改没有按预期工作,并返回错误的值。


That said, even if Windows did set the priority as expected, the .NET code still wouldn't work in some cases.也就是说,即使 Windows 确实按预期设置了优先级,.NET 代码在某些情况下仍然无法工作。 For instance, imagine you were setting the PriorityClass to BelowNormal .例如,假设您将PriorityClass设置为BelowNormal That value would be stored locally in the Process object, as explained above.如上所述,该值将本地存储在Process对象中。 Then if you change the priority again but from the task manager, just like before .NET won't be aware of it and will return the old value.然后,如果您再次更改优先级,但从任务管理器中更改,就像之前一样,.NET 不会意识到它并返回旧值。

If you absolutely need an up-to-date information, first call process.Refresh() to clear the locally stored value.如果您绝对需要最新信息,请首先调用process.Refresh()以清除本地存储的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM