아래 내용은 Process.Start() 이후
process.PriorityClass = ProcessPriorityClass.BelowNormal;
처리를 해줘야 효과를 볼수 있다.
public static class ProcessHelper
{
[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;
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);
}
}
}
2.
아래 내용은 process.PriorityClass = ProcessPriorityClass.BelowNormal 처리를 하지 않아도 효과를 볼수 있다.
이 내용이 확실하게 제어를 해주는것 같다
public class ProcessManager
{
[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
}
public static void ThrottleProcess(Process process)
{
//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 !");
}
}
}
사용예시
Process process = new Process();
process.EnableRaisingEvents = false;
process.StartInfo.FileName = "Test.exe";
//process.StartInfo.Verb = "Open";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
//process.StartInfo.Arguments = argument;
process.Start();
// 1번 방법
process.PriorityClass = ProcessPriorityClass.BelowNormal;
ProcessHelper.ThrottleProcess(process.Id, 0.5);
// 2번 방법
ProcessManager.ThrottleProcess(process);
'C# > Winform' 카테고리의 다른 글
[C#] (401) Unauthorized 에러 (0) | 2019.09.19 |
---|---|
[C#] Nuget 캐시 지우기 (0) | 2019.09.19 |
[C#] 이미지를 바이트 배열로 변환하기 (Image to byte[]) (0) | 2019.05.24 |
[C#.NET/C#] 빗썸 Open API 를 이용해 가상화폐정보 가져오기 (0) | 2019.05.21 |
[C#.NET/C#] 디자인모드에서 편집가능한 유저 컨트롤 만들기 (ParentControlDesigner) (0) | 2019.05.21 |