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

2

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

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

Он отображается только как "Высокий" приоритет в диспетчере задач:

Изображение 174551

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

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

  • 0
    Может быть, использование ILSpy может помочь.
Теги:
process

1 ответ

1
Лучший ответ

Настоящий виновник здесь - 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);
        }
    }

После нескольких проверок SetPriorityClass он вызывает Windows API SetPriorityClass, а затем проверяет код возврата. Если возникает ошибка, выдается исключение. В противном случае он локально сохраняет значение нового приоритета (чтобы при чтении значения PriorityClass ему не приходилось вызывать Windows обратно, чтобы проверить его).

В некоторых случаях Windows будет отказывать в изменении приоритета (например, как вы заметили, теперь вам нужны права администратора для установки приоритета в реальном времени). Хитрость в том, что Windows молча отрицает изменение приоритета и не возвращает код ошибки. Как задокументировано здесь:

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

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


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

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

  • 0
    process.PriorityClass = ProcessPriorityClass.RealTime; Console.WriteLine($"Priority class cached: {process.PriorityClass}"); process.Refresh(); Console.WriteLine($"Actual priority class: {process.PriorityClass}"); При запуске без прав администратора печатает: Priority class assumed: RealTime Actual priority class: High Так что все верно, проблема в том, что класс Process кэширует предполагаемое значение, а не получает его из Windows.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню