■ 프로세스 CPU 사용률을 제한하는 방법을 보여준다.
▶ ProcessHelper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
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 } } |