1

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;
        }
Nar Jovan
  • 85
  • 10
  • 1
    Its not your job to check CPU-usage. If your program needs the CPU, then just do it. Your OS is the one, who need to manage the resources. Almost all modern CPU and OS are changing the speed of your CPU depends on required performance. – akop Aug 08 '19 at 08:20
  • @user6537157 The problem is my program on server, and once it start the process it use 100%, so that slows else processes. – Nar Jovan Aug 08 '19 at 08:23
  • Then you have other problems in your program. Maybe its better, that you find out why your program consumes so much CPU-time. But dont build a "cpu limiter" in your code - it wont make you happy. – akop Aug 08 '19 at 08:27
  • @user6537157 process start program, and that program is not created by me, so how do i find out? – Nar Jovan Aug 08 '19 at 08:29
  • You want to limit a other program? Its even worse, then you dont know how the other program react on your "limitation". My tip: Give the application a lower cpu-priority and try investigate the problem (maybe talk to the original developers or use a other software). – akop Aug 08 '19 at 08:34
  • @user6537157 Process class created to use other programs isn't it? – Nar Jovan Aug 08 '19 at 08:38
  • Yes, but not interrupt them, when they use to many ressources. – akop Aug 08 '19 at 08:42
  • @user6537157 is there a way to limit cpu usage for specific program other way? – Nar Jovan Aug 08 '19 at 08:43
  • `ThrottleProcess()` never returns. – CodeCaster Aug 08 '19 at 08:46
  • @CodeCaster Ok, but why that guy has so many upvotes under his post? Do you have idea how to fix my problem? – Nar Jovan Aug 08 '19 at 08:49
  • Its a job for the OS. I dont know tools for it, but maybe this will help you https://www.technorms.com/46600/regulate-cpu-usage-in-windows-10. – akop Aug 08 '19 at 08:49

1 Answers1

1

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.

Nar Jovan
  • 85
  • 10