■ 프로세스 CPU 사용률 제한하기

------------------------------------------------------------------------------------------------------------------------


TestSolution.zip


ProcessHelper.cs

 

 

using System;

using System.Diagnostics;

using System.Runtime.InteropServices;

using System.Threading;

 

namespace TestProject

{

    /// <summary>

    /// 프로세스 헬퍼

    /// </summary>

    public static class ProcessHelper

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region 스레드 열기 - OpenThread(threadAccess, inheritHandle, threadID)

 

        /// <summary>

        /// 스레드 열기

        /// </summary>

        /// <param name="threadAccess">스레드 액세스</param>

        /// <param name="inheritHandle">상속 핸들</param>

        /// <param name="threadID">스레드 ID</param>

        /// <returns>스레드 핸들</returns>

        [DllImport("kernel32.dll")]

        private static extern IntPtr OpenThread(ThreadAccess threadAccess, bool inheritHandle, uint threadID);

 

        #endregion

        #region 스레드 실행 일시 중지하기 - SuspendThread(threadHandle)

 

        /// <summary>

        /// 스레드 실행 일시 중지하기

        /// </summary>

        /// <param name="threadHandle">스레드 핸들</param>

        /// <returns>처리 결과</returns>

        [DllImport("kernel32.dll")]

        private static extern uint SuspendThread(IntPtr threadHandle);

 

        #endregion

        #region 스레드 다시 실행하기 - ResumeThread(threadHandle)

 

        /// <summary>

        /// 스레드 다시 실행하기

        /// </summary>

        /// <param name="threadHandle">스레드 핸들</param>

        /// <returns>처리 결과</returns>

        [DllImport("kernel32.dll")]

        private static extern int ResumeThread(IntPtr threadHandle);

 

        #endregion

        #region 핸들 닫기 - CloseHandle(threadHandle)

 

        /// <summary>

        /// 핸들 닫기

        /// </summary>

        /// <param name="threadHandle">스레드 핸들</param>

        /// <returns>처리 결과</returns>

        [DllImport("kernel32.dll")]

        private static extern int CloseHandle(IntPtr threadHandle);

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 프로세스 실행 일시 중지하기 - SuspendProcess(processID)

 

        /// <summary>

        /// 프로세스 실행 일시 중지하기

        /// </summary>

        /// <param name="processID">프로세스 ID</param>

        public static void SuspendProcess(int processID)

        {

            Process process = Process.GetProcessById(processID);

 

            if(process.ProcessName == string.Empty)

            {

                return;

            }

 

            foreach(ProcessThread processThread in process.Threads)

            {

                IntPtr threadHandle = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)processThread.Id);

 

                if(threadHandle == IntPtr.Zero)

                {

                    continue;

                }

 

                SuspendThread(threadHandle);

 

                CloseHandle(threadHandle);

            }

        }

 

        #endregion

        #region 프로세스 다시 실행하기 - ResumeProcess(processiD)

 

        /// <summary>

        /// 프로세스 다시 실행하기

        /// </summary>

        /// <param name="processiD">프로세스 ID</param>

        public static void ResumeProcess(int processiD)

        {

            Process process = Process.GetProcessById(processiD);

 

            if(process.ProcessName == string.Empty)

            {

                return;

            }

 

            foreach(ProcessThread processThread in process.Threads)

            {

                IntPtr threadHandle = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)processThread.Id);

 

                if(threadHandle == IntPtr.Zero)

                {

                    continue;

                }

 

                var suspendCount = 0;

 

                do

                {

                    suspendCount = ResumeThread(threadHandle);

                }

                while(suspendCount > 0);

 

                CloseHandle(threadHandle);

            }

        }

 

        #endregion

 

        #region 프로세스 조절하기 - ThrottleProcess(processID, limitCPURate)

 

        /// <summary>

        /// 프로세스 조절하기

        /// </summary>

        /// <param name="processID">프로세스 ID</param>

        /// <param name="limitUsage">제한 사용률</param>

        public static void ThrottleProcess(int processID, double limitUsage)

        {

            Process process = Process.GetProcessById(processID);

 

            string instanceName = process.ProcessName;

 

            PerformanceCounter counter = new PerformanceCounter("Process", "% Processor Time", instanceName);

 

            int interval = 100;

 

            while(true)

            {

                Thread.Sleep(interval);

 

                float currentUsage = counter.NextValue() / Environment.ProcessorCount;

 

                if(currentUsage < limitUsage)

                {

                    continue;

                }

 

                double suspensionTime = (currentUsage - limitUsage) / currentUsage * interval;

 

                SuspendProcess(processID);

 

                Thread.Sleep((int)suspensionTime);

 

                ResumeProcess(processID);

            }

        }

 

        #endregion

    }

}

 

 

Program.cs

 

 

using System;

using System.Diagnostics;

 

namespace TestProject

{

    /// <summary>

    /// 프로그램

    /// </summary>

    class Program

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 프로세스

        /// </summary>

        private static Process _process = null;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region 프로그램 시작하기 - Main()

 

        /// <summary>

        /// 프로그램 시작하기

        /// </summary>

        private static void Main()

        {

            Console.CancelKeyPress += Console_CancelKeyPress;

 

            _process = new Process();

 

            _process.EnableRaisingEvents   = false;

            _process.StartInfo.FileName    = "TestWorker.exe";

            _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

 

            _process.Start();

 

            _process.PriorityClass = ProcessPriorityClass.BelowNormal;

 

            ProcessHelper.ThrottleProcess(_process.Id, 0.3);

        }

 

        #endregion

 

        #region 콘솔 취소 키 PRESS 처리하기 - Console_CancelKeyPress(sender, e)

 

        /// <summary>

        /// 콘솔 취소 키 PRESS 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)

        {

            ProcessHelper.ResumeProcess(_process.Id);

 

            _process.Kill();

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요