В чем разница между классами приоритетов .NET Real-Time и TaskMgr Real-time? - PullRequest
0 голосов
/ 05 января 2019

Когда я устанавливаю класс приоритета процесса в реальном времени в .NET:

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

Появляется только как «Высокий» приоритет в диспетчере задач:

enter image description here

Если я вручную установлю его в реальном времени в диспетчере задач, а затем снова выполню Process.GetCurrentProcess(), ProcessPriorityClass по-прежнему будет отображаться как ProcessPriorityClass.RealTime.

Если я запускаю приложение от имени администратора, класс приоритетов меняется на Реальное время, как сообщает диспетчер задач. Таким образом, кажется, что при работе от имени обычного пользователя вы можете установить его в RealTime, и он будет сообщаться как таковой .NET, но фактический приоритет процесса на самом деле просто высокий. Почему .NET и TaskManager сообщают о разных значениях в этом случае?

1 Ответ

0 голосов
/ 05 января 2019

Настоящий виновник здесь - Windows.

Установщик свойства PriorityClass прост:

 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 молча запрещает изменение приоритета и не возвращает код ошибки . Как задокументировано здесь :

Обратите внимание, что вызов SetPriorityClass () может вернуть успех, даже если приоритет не был установлен в REALTIME_PRIORITY_CLASS, потому что, если у вас нет разрешения Увеличение приоритета планирования, запрос REALTIME_PRIORITY_CLASS интерпретируется как запрос на самый высокий приоритет класс разрешен в текущем аккаунте.

Полагаю, это сделано для того, чтобы избежать взлома устаревших приложений, которые не ожидают, что их вызов не будет выполнен. По этой причине ваше приложение .NET не знает, что изменение приоритета не сработало, как ожидалось, и возвращает неправильное значение.


Тем не менее, даже если Windows установит приоритет должным образом, в некоторых случаях код .NET все равно не будет работать. Например, представьте, что вы устанавливаете PriorityClass на BelowNormal. Это значение будет храниться локально в объекте Process, как описано выше. Затем, если вы снова измените приоритет, но из диспетчера задач, как и раньше, .NET не узнает об этом и вернет старое значение.

Если вам абсолютно необходима актуальная информация, сначала позвоните process.Refresh(), чтобы очистить локально сохраненное значение.

...