Настоящий виновник здесь - 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()
, чтобы очистить локально сохраненное значение.