Как ограничить использование ЦП в C#

Я делаю программу на С#. Моя программа вызывает другую программу. Проблема в том, что программа, которую я вызываю, потребляет 100% процессорного времени. Поэтому я хочу ограничить его постоянным процентом использования ЦП. Является ли это возможным? Как?


person Mr.Bua    schedule 10.12.2009    source источник


Ответы (3)


Есть ли причина, по которой вы хотите ограничить его определенным процентом использования ЦП? Как насчет того, чтобы запустить его с более низким приоритетом, чтобы он по-прежнему использовал 100% ЦП, когда больше ничего не требуется, но переводился в фоновый режим, когда выполняются более важные процессы?

person Tal Pressman    schedule 10.12.2009
comment
Это по-прежнему дает администраторам серверов возможность контролировать распределение обработки. Пока ЦП не используется, может быть хорошей идеей дать ему 100%. - person Russell; 10.12.2009
comment
Можно ли запускать процессор на 100% 24/24? - person Mr.Bua; 10.12.2009
comment
Процессор предназначен для обработки вещей... Нет причин не использовать его. Конечно, вы должны убедиться, что нет ошибок, из-за которых вы тратите процессорное время впустую, сохраняя его на 100%, даже если ничего полезного не происходит, но кроме этого обычно нет причин ограничивать использование ЦП. - person Tal Pressman; 15.12.2009

Это все еще относительно высокий результат в поисковых системах, поэтому я добавлю ответ на этот старый вопрос:

ДА!

В 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());
person Lukas Rieger    schedule 13.10.2020

Операционная система должна управлять разделением времени между вашими двумя приложениями. Вероятно, есть веская причина, по которой ваше приложение использует 100% ЦП, оно что-то вычисляет. Если вам нужно дождаться завершения другого процесса, вы можете использовать Process.WaitForExit чтобы остановить выполнение вызывающего потока, пока другой процесс не завершится.

person stimms    schedule 10.12.2009