Reputation: 204
I want my Process does not cross 70% of CPU usage. And i found solution in here: How can I programmatically limit my program's CPU usage to below 70%? . Here is the class I am trying to use from that link:
public class ProcessManager
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int CloseHandle(IntPtr hThread);
public static void ThrottleProcess(int processId, double limit)
{
var process = Process.GetProcessById(processId);
var processName = process.ProcessName;
var p = new PerformanceCounter("Process", "% Processor Time", processName);
while (true)
{
var interval = 100;
Thread.Sleep(interval);
var currentUsage = p.NextValue() / Environment.ProcessorCount;
if (currentUsage < limit) continue; // Infinant loop ?
var suspensionTime = (currentUsage-limit) / currentUsage * interval;
SuspendProcess(processId);
Thread.Sleep((int)suspensionTime);
ResumeProcess(processId);
}
}
private static void SuspendProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
SuspendThread(pOpenThread);
CloseHandle(pOpenThread);
}
}
private static void ResumeProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
var suspendCount = 0;
do
{
suspendCount = ResumeThread(pOpenThread);
} while (suspendCount > 0);
CloseHandle(pOpenThread);
}
}
}
The author of this code under his post left the comment that says, use ThrottleProcess after
Process.Start(). I did it, but it seems like right after Process has started, it gets inside ThrottleProcess and get stucks inside While
loop. And i can't figure out what to do with it, maybe it should run method asynchronously? Like Process should run independently of Throttle isn't it?
Here's my Process method:
private string startProcess(string fileName, string args)
{
// Create Process manager
var ProcessManager = new ProcessManager();
string result = "";
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = fileName;
psi.Arguments = args;
psi.WorkingDirectory = "...\\TempFolder";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.StandardOutputEncoding = System.Text.Encoding.UTF8;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
p = Process.Start(psi);
// After it gots here, process get stuck inside while loop
ProcessManager.ThrottleProcess(p.Id , 1);
try
{
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
if (p.ExitCode != 0)
throw new Exception("Program returned with error code " + p.ExitCode);
result = output.ToString();
}
catch (Exception ex)
{
result = ex.ToString();
}
finally
{
p.Close();
p.Dispose();
}
return result;
}
Upvotes: 1
Views: 431
Reputation: 204
Turns out you can set affinity for a process. Affinity it is the quantity of cores that your process will use. The only thing you need, is just to add for your Process method this string:
Process p = new Process();
p.ProcessorAffinity = (IntPtr)1; // or any number (your cores)
It decreased CPU overload to minimum for my case.
Upvotes: 1