Я делаю программу на С#. Моя программа вызывает другую программу. Проблема в том, что программа, которую я вызываю, потребляет 100% процессорного времени. Поэтому я хочу ограничить его постоянным процентом использования ЦП. Является ли это возможным? Как?
Как ограничить использование ЦП в C#
Ответы (3)
Есть ли причина, по которой вы хотите ограничить его определенным процентом использования ЦП? Как насчет того, чтобы запустить его с более низким приоритетом, чтобы он по-прежнему использовал 100% ЦП, когда больше ничего не требуется, но переводился в фоновый режим, когда выполняются более важные процессы?
Это все еще относительно высокий результат в поисковых системах, поэтому я добавлю ответ на этот старый вопрос:
ДА!
В Windows 8+ вы можете ограничить потребление ЦП процессами с помощью заданий:
Вызовите SetInformationJobObject с JobObjectCpuRateControlInformation и установите JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP
.
Job API является родным, поэтому вам придется p/вызвать его:
public static class Win32
{
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11,
JobObjectCpuRateControlInformation = 15
}
[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public JOBOBJECTLIMIT LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public UInt32 ActiveProcessLimit;
public Int64 Affinity;
public UInt32 PriorityClass;
public UInt32 SchedulingClass;
}
[Flags]
public enum JOBOBJECTLIMIT : uint
{
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000,
JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200,
JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100,
JOB_OBJECT_LIMIT_WORKINGSET = 0x00000001
}
[StructLayout(LayoutKind.Sequential)]
public struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}
public enum CpuFlags : UInt32
{
JOB_OBJECT_CPU_RATE_CONTROL_ENABLE = 0x00000001,
JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED = 0x00000002,
JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP = 0x00000004
}
// https://stackoverflow.com/a/31361144
[StructLayout(LayoutKind.Explicit)]
//[CLSCompliant(false)]
public struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
{
[FieldOffset(0)]
public CpuFlags ControlFlags;
[FieldOffset(4)]
public UInt32 CpuRate;
[FieldOffset(4)]
public UInt32 Weight;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name);
[DllImport("kernel32.dll")]
internal static extern bool SetInformationJobObject(IntPtr job, JobObjectInfoType infoType,
ref JOBOBJECT_EXTENDED_LIMIT_INFORMATION lpJobObjectInfo, uint cbJobObjectInfoLength);
[DllImport("kernel32.dll")]
internal static extern bool SetInformationJobObject(IntPtr job, JobObjectInfoType infoType,
ref JOBOBJECT_CPU_RATE_CONTROL_INFORMATION lpJobObjectInfo, uint cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
}
public class JobUtils
{
///
public static void SetExtendedLimitInformationJobObject(IntPtr jobHandle, JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo)
{
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
if (!Win32.SetInformationJobObject(jobHandle, JobObjectInfoType.ExtendedLimitInformation,
ref extendedInfo, (uint)length))
{
throw new Win32Exception();
}
}
///
public static void SetCpuRateControlInformationJobObject(IntPtr jobHandle, JOBOBJECT_CPU_RATE_CONTROL_INFORMATION cpuRateControlInformation)
{
int length = Marshal.SizeOf(typeof(JOBOBJECT_CPU_RATE_CONTROL_INFORMATION));
if (!Win32.SetInformationJobObject(jobHandle, JobObjectInfoType.JobObjectCpuRateControlInformation,
ref cpuRateControlInformation, (uint)length))
{
throw new Win32Exception();
}
}
///
public static void AssignProcessToJobObject(IntPtr job, Process process)
{
bool success = Win32.AssignProcessToJobObject(job, process.Handle);
if (!success && !process.HasExited)
throw new Win32Exception();
}
}
// test code
var cpuLimit = 20; // 20%
var job = Win32.CreateJobObject(IntPtr.Zero, null);
JobUtils.SetCpuRateControlInformationJobObject(job, new Win32.JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
{
ControlFlags = Win32.CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | Win32.CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP,
CpuRate = (uint)cpuLimit * 100
});
JobUtils.AssignProcessToJobObject(job, Process.GetCurrentProcess());
Операционная система должна управлять разделением времени между вашими двумя приложениями. Вероятно, есть веская причина, по которой ваше приложение использует 100% ЦП, оно что-то вычисляет. Если вам нужно дождаться завершения другого процесса, вы можете использовать Process.WaitForExit чтобы остановить выполнение вызывающего потока, пока другой процесс не завершится.