你能限制.NET进程对象的CPU使用率吗?

时间:2012-03-20 19:11:51

标签: c# .net winapi unsafe

我正在贡献的一个应用程序,用于激活用C语言编写的组件。

C进程会进行一些非常繁重的运算,如果不小心可以真正打击你的CPU。

有没有办法为.NET生成的外部进程设置限制?

我已经看到this artivcle在操作系统级别设置硬内存限制,CPU有类似的东西吗?

2 个答案:

答案 0 :(得分:9)

不在Windows中。您可以降低进程优先级,这将降低在CPU上调度有问题的进程并干扰其他(可能是更高优先级)应用程序的可能性。例如,来自http://dotnet-concepts-queries-interviews.blogspot.com/2007/05/how-to-set-process-priority-in-net.html

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

请记住,如果您没有在框中运行任何其他内容,您可能希望此过程消耗所有可用的CPU。

如果它位于多处理器盒上,您还可以设置CPU亲和力,将处理限制为某些核心,并让其他核心的其他应用程序空闲。通常,OS在调度应用程序线程方面做得很好,因此设置进程优先级可能会有更好的整体结果。见How Can I Set Processor Affinity in .NET?

答案 1 :(得分:9)

我遇到了同样的问题。 我通过使用SetInformationJobObject Kernel32 Win Api和JOBOBJECT_CPU_RATE_CONTROL_INFORMATION结构来解决它。

我更大的问题是在c#中表示这个结构(使用“union”)。 希望我找到了这种结构的“单声道”描述。

[StructLayout(LayoutKind.Explicit)]
//[CLSCompliant(false)]
struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
{
    [FieldOffset(0)]
    public UInt32 ControlFlags;
    [FieldOffset(4)]
    public UInt32 CpuRate;
    [FieldOffset(4)]
    public UInt32 Weight;
}

激活Cpu限制:

ControlFlags = 0x00000001 | 0x00000004;
CpuRate = percent of max usage  * 100 (ex 50 * 100 for a 50% limit)

以下示例功能齐全。

我希望有帮助。

亲切的问候

-Thierry -

[DllImport("kernel32.dll", EntryPoint = "CreateJobObjectW", CharSet = CharSet.Unicode)]
public static extern IntPtr CreateJobObject(SecurityAttributes JobAttributes, string lpName);

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);

[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

public class SecurityAttributes
{

    public int nLength; 
    public IntPtr pSecurityDescriptor; 
    public bool bInheritHandle;

    public SecurityAttributes()
    {
        this.bInheritHandle = true;
        this.nLength = 0;
        this.pSecurityDescriptor = IntPtr.Zero;
    }
}

public enum JOBOBJECTINFOCLASS
{
    JobObjectAssociateCompletionPortInformation = 7,
    JobObjectBasicLimitInformation = 2,
    JobObjectBasicUIRestrictions = 4,
    JobObjectEndOfJobTimeInformation = 6,
    JobObjectExtendedLimitInformation = 9,
    JobObjectSecurityLimitInformation = 5,
    JobObjectCpuRateControlInformation = 15
}

[StructLayout(LayoutKind.Explicit)]
//[CLSCompliant(false)]
struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
{
    [FieldOffset(0)]
    public UInt32 ControlFlags;
    [FieldOffset(4)]
    public UInt32 CpuRate;
    [FieldOffset(4)]
    public UInt32 Weight;
}

public enum CpuFlags
{
    JOB_OBJECT_CPU_RATE_CONTROL_ENABLE = 0x00000001,
    JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED = 0x00000002,
    JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP = 0x00000004
}

/// <summary>
/// Launch the legacy application with some options set.
/// </summary>
static void DoExecuteProgramm()
{
    // prepare the process to execute
    var startInfo = new ProcessStartInfo();
    . . . . . 
    // Start the process
    var process = Process.Start(startInfo);

    //Limit the CPU usage to 45%
    var jobHandle = CreateJobObject(null, null);
    AssignProcessToJobObject(jobHandle, process.Handle);
    var cpuLimits = new JOBOBJECT_CPU_RATE_CONTROL_INFORMATION();
    cpuLimits.ControlFlags = (UInt32)(CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP);
    cpuLimits.CpuRate = 45 * 100; // Limit CPu usage to 45%
    var pointerToJobCpuLimits = Marshal.AllocHGlobal(Marshal.SizeOf(cpuLimits));
    Marshal.StructureToPtr(cpuLimits, pointerToJobCpuLimits, false);
    if (!SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectCpuRateControlInformation, pointerToJobCpuLimits, (uint)Marshal.SizeOf(cpuLimits)))
    {
        Console.WriteLine("Error !");
    }
}