Can you limit the CPU usage on a .NET Process Object?
Not in Windows. You can lower the process priority though, which will reduce the likelihood that the problematic process will be scheduled on the CPU and interfere with other (presumably higher priority) applications. For instance, from http://dotnet-concepts-queries-interviews.blogspot.com/2007/05/how-to-set-process-priority-in-net.html:
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal;
Keep in mind, if you don't have anything else running on the box, you probably want this process to consume all of the available CPU.
You can also set the CPU affinity if it is on a multi-processor box, limiting the processing to certain cores and leaving others free for other applications. Generally the OS does a good job of scheduling application threads though, so setting the process priority is likely to have a better overall result. See How Can I Set Processor Affinity in .NET?
I had the same problem. I solved it by using SetInformationJobObject Kernel32 Win Api and JOBOBJECT_CPU_RATE_CONTROL_INFORMATION struct.
My bigger problem was to represent this structure in c# (uses "union"). Hopefully, I found a "mono" description of this structure.
[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;
}
To activate the Cpu limitation :
ControlFlags = 0x00000001 | 0x00000004;
CpuRate = percent of max usage * 100 (ex 50 * 100 for a 50% limit)
The sample below is fully functional.
I hope that's help.
Kind Regards
-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 !");
}
}