簡體   English   中英

如何在 C# 中限制 CPU 使用率

[英]How to Limit CPU Usage in C#

我正在制作一個 C# 程序。 我的程序正在調用另一個程序。 問題是我正在調用的程序消耗了 100% 的 CPU。 所以我想將其限制為 CPU 使用率的恆定百分比。 是否有可能? 如何?

是否有任何理由要將其限制為特定百分比的 CPU 使用率? 如何以較低的優先級運行它,以便在沒有其他需要時仍然使用 100% 的 CPU,但在有更重要的進程運行時被置於后台?

這在搜索引擎中還是比較高的結果,所以我來補充一下這個老問題的答案:

是的!

使用 Windows 8+,您可以使用作業限制進程的 CPU 消耗:

使用JobObjectCpuRateControlInformation調用SetInformationJobObject並設置JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP

作業 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% 的 CPU 可能有一個很好的理由,它正在計算一些東西。 如果您需要等待另一個進程的完成,那么您可以使用Process.WaitForExit在另一個進程完成時暫停調用線程的執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM