728x90
반응형
728x170
▶ CPUHelper.cs
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
namespace TestProject
{
/// <summary>
/// CPU 헬퍼
/// </summary>
public class CPUHelper : IDisposable
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// CPU 사용률 배열
/// </summary>
public int[] CPUUsageRatioArray;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 백그라운드 작업자
/// </summary>
private BackgroundWorker worker;
/// <summary>
/// 성능 카운터 배열
/// </summary>
private PerformanceCounter[] performanceCounterArray;
/// <summary>
/// 리소스 해제 여부
/// </summary>
private bool isDisposed = false;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 프로세서 카운트 - ProcessorCount
/// <summary>
/// 프로세서 카운트
/// </summary>
public int ProcessorCount { get; private set; }
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - CPUHelper()
/// <summary>
/// 생성자
/// </summary>
public CPUHelper()
{
ProcessorCount = Environment.ProcessorCount;
this.performanceCounterArray = new PerformanceCounter[ProcessorCount];
for(int i = 0; i < ProcessorCount; i++)
{
this.performanceCounterArray[i] = new PerformanceCounter();
this.performanceCounterArray[i].CategoryName = "Processor";
this.performanceCounterArray[i].CounterName = "% Processor Time";
this.performanceCounterArray[i].InstanceName = i.ToString();
}
CPUUsageRatioArray = new int[ProcessorCount];
this.worker = new BackgroundWorker();
this.worker.WorkerSupportsCancellation = true;
this.worker.DoWork += worker_DoWork;
this.worker.RunWorkerAsync();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Destructor
#region 소멸자 - ~CPUHelper()
/// <summary>
/// 소멸자
/// </summary>
~CPUHelper()
{
Dispose(false);
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
//////////////////////////////////////////////////////////////////////////////// Function
#region CPU 사용률 구하기 - GetCPUUsageRatio(processorID)
/// <summary>
/// CPU 사용률 구하기
/// </summary>
/// <param name="processorID">프로세서 ID</param>
/// <returns>CPU 사용률</returns>
public int GetCPUUsageRatio(int processorID)
{
return CPUUsageRatioArray[processorID];
}
#endregion
#region 리소스 해제하기 - Dispose()
/// <summary>
/// 리소스 해제하기
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Protected
//////////////////////////////////////////////////////////////////////////////// Function
#region 리소스 해제하기 - Dispose(isDisposing)
/// <summary>
/// 리소스 해제하기
/// </summary>
/// <param name="isDisposing">리소스 해제 여부</param>
protected virtual void Dispose(bool isDisposing)
{
if(isDisposed)
{
return;
}
this.worker.CancelAsync();
this.worker.Dispose();
for(int i = 0; i < this.performanceCounterArray.Length; i++)
{
this.performanceCounterArray[i].Dispose();
}
this.isDisposed = true;
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 백그라운드 작업자 작업시 처리하기 - worker_DoWork(sender, e)
/// <summary>
/// 백그라운드 작업자 작업시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
while(true)
{
for(int i = 0; i < ProcessorCount; i++)
{
SetCPUUsageRatio(i);
}
Thread.Sleep(1000);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region CPU 사용률 설정하기 - SetCPUUsageRatio(processorID)
/// <summary>
/// CPU 사용률 설정하기
/// </summary>
/// <param name="processorID">프로세서 ID</param>
private void SetCPUUsageRatio(int processorID)
{
float value = this.performanceCounterArray[processorID].NextValue();
CPUUsageRatioArray[processorID] = (int)value;
}
#endregion
}
}
728x90
▶ CPULoadHelper.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
namespace TestProject
{
/// <summary>
/// CPU 부하 헬퍼
/// </summary>
public class CPULoadHelper : IDisposable
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// CPU 헬퍼
/// </summary>
private CPUHelper cpuHelper;
/// <summary>
/// 리셋 이벤트 배열
/// </summary>
private ManualResetEvent[] resetEventArray;
/// <summary>
/// 스레드 배열
/// </summary>
private Thread[] threadArray;
/// <summary>
/// 타겟 CPU 사용률 배열
/// </summary>
private int[] targetCPUUsageRatioArray = new int[Environment.ProcessorCount];
/// <summary>
/// 프로세서 스레드 딕셔너리
/// </summary>
private Dictionary<int, int> processorThreadDictionary;
/// <summary>
/// 리소스 해제 여부
/// </summary>
private bool isDisposed = false;
/// <summary>
/// 백그라운드 작업자
/// </summary>
private BackgroundWorker worker;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 프로세서 카운트 - ProcessorCount
/// <summary>
/// 프로세서 카운트
/// </summary>
private int ProcessorCount { get; set; }
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - CPULoadHelper()
/// <summary>
/// 생성자
/// </summary>
public CPULoadHelper()
{
ProcessorCount = Environment.ProcessorCount;
this.threadArray = new Thread[ProcessorCount];
this.worker = new BackgroundWorker();
this.worker.DoWork += worker_DoWork;
this.cpuHelper = new CPUHelper();
this.processorThreadDictionary = new Dictionary<int, int>();
SetAffinityForAllThreads();
this.resetEventArray = new ManualResetEvent[ProcessorCount];
for(int i = 0; i < ProcessorCount; i++)
{
this.resetEventArray[i] = new ManualResetEvent(false);
}
this.worker.RunWorkerAsync();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
#region 소멸자 - ~CPULoadHelper()
/// <summary>
/// 소멸자
/// </summary>
~CPULoadHelper()
{
Dispose(false);
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
//////////////////////////////////////////////////////////////////////////////// Function
#region 타겟 CPU 사용률 설정하기 - SetTargetCPUUsageRatio(processorID, cpuUsageRatio)
/// <summary>
/// 타겟 CPU 사용률 설정하기
/// </summary>
/// <param name="processorID">프로세서 ID</param>
/// <param name="cpuUsageRatio">CPU 사용률</param>
public void SetTargetCPUUsageRatio(int processorID, int cpuUsageRatio)
{
this.targetCPUUsageRatioArray[processorID] = cpuUsageRatio;
}
#endregion
#region 리소스 해제하기 - Dispose()
/// <summary>
/// 리소스 해제하기
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Protected
//////////////////////////////////////////////////////////////////////////////// Function
#region 리소스 해제하기 - Dispose(isDisposing)
/// <summary>
/// 리소스 해제하기
/// </summary>
/// <param name="isDisposing">리소스 해제 여부</param>
protected virtual void Dispose(bool isDisposing)
{
if(isDisposed)
{
return;
}
this.cpuHelper.Dispose();
for(int i = 0; i < this.threadArray.Length; i++)
{
try
{
this.threadArray[i].Abort();
}
catch
{
}
}
for(int i = 0; i < this.resetEventArray.Length; i++)
{
this.resetEventArray[i].Dispose();
}
isDisposed = true;
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 백그라운드 작업자 작업시 처리하기 - worker_DoWork(sender, e)
/// <summary>
/// 백그라운드 작업자 작업시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
for(int i = 0; i < ProcessorCount; i++)
{
this.threadArray[i] = CreateThreadOnProcessor(i);
Thread.Sleep(500);
}
while(true)
{
for(int i = 0; i < ProcessorCount; i++)
{
if(this.cpuHelper.GetCPUUsageRatio(i) > this.targetCPUUsageRatioArray[i])
{
this.resetEventArray[i].Reset();
}
else
{
this.resetEventArray[i].Set();
}
}
Thread.Sleep(2000);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 모든 스레드에 대한 선호도 설정하기 - SetAffinityForAllThreads()
/// <summary>
/// 모든 스레드에 대한 선호도 설정하기
/// </summary>
private void SetAffinityForAllThreads()
{
ProcessThreadCollection collection = Process.GetCurrentProcess().Threads;
IEnumerator enumerator = collection.GetEnumerator();
int x = 1 << (0);
while(enumerator.MoveNext())
{
try
{
ProcessThread processThread = (ProcessThread)enumerator.Current;
processThread.ProcessorAffinity = new IntPtr(x);
}
catch(Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
#endregion
#region 현재 프로세스의 스레드 ID 리스트 구하기 - GetCurrentProcessThreadIDList()
/// <summary>
/// 현재 프로세스의 스레드 ID 리스트 구하기
/// </summary>
/// <returns>스레드 ID 리스트</returns>
private List<int> GetCurrentProcessThreadIDList()
{
ProcessThreadCollection collection = Process.GetCurrentProcess().Threads;
IEnumerator enumerator = collection.GetEnumerator();
List<int> list = new List<int>();
while(enumerator.MoveNext())
{
ProcessThread processThread = (ProcessThread)enumerator.Current;
list.Add(processThread.Id);
}
return list;
}
#endregion
#region 스레드 ID로 프로세스 스레드 구하기 - GetProcessThreadByThreadID(threadID)
/// <summary>
/// 스레드 ID로 프로세스 스레드 구하기
/// </summary>
/// <param name="threadID">스레드 ID</param>
/// <returns>프로세스 스레드</returns>
private ProcessThread GetProcessThreadByThreadID(int threadID)
{
ProcessThreadCollection collection = Process.GetCurrentProcess().Threads;
IEnumerator enumerator = collection.GetEnumerator();
ProcessThread processThread = null;
while(enumerator.MoveNext())
{
ProcessThread currentProcessThread = (ProcessThread)enumerator.Current;
if(currentProcessThread.Id == threadID)
{
processThread = currentProcessThread;
break;
}
}
return processThread;
}
#endregion
#region CPU 로드 생성하기 - CreateCPULoad(processorID)
/// <summary>
/// CPU 로드 생성하기
/// </summary>
private void CreateCPULoad(int processorID)
{
while(true)
{
this.resetEventArray[processorID].WaitOne();
int time = 10000 - this.targetCPUUsageRatioArray[processorID] * 100;
Thread.Sleep(new TimeSpan(time));
}
}
#endregion
#region 프로세서 스레드 생성하기 - CreateThreadOnProcessor(processorID)
/// <summary>
/// 프로세서 스레드 생성하기
/// </summary>
/// <param name="processorID">프로세서 ID</param>
/// <returns>스레드</returns>
private Thread CreateThreadOnProcessor(int processorID)
{
List<int> currentList = GetCurrentProcessThreadIDList();
Thread thread = new Thread(() => CreateCPULoad(processorID));
thread.Start();
List<int> newList = GetCurrentProcessThreadIDList();
newList.RemoveAll(Item => currentList.Contains(Item));
ProcessThread processThread = GetProcessThreadByThreadID(newList[0]);
processThread.ProcessorAffinity = new IntPtr(1 << processorID);
processorThreadDictionary.Add(processThread.Id, processorID);
return thread;
}
#endregion
}
}
300x250
▶ MainForm.cs
using System;
using System.Drawing;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// CPU 부하 헬퍼
/// </summary>
private CPULoadHelper cpuLoadHelper;
/// <summary>
/// 프로세서 카운트
/// </summary>
private int processorCount = Environment.ProcessorCount;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
#region 이벤트를 설정한다.
Load += Form_Load;
FormClosing += Form_FormClosing;
this.closeButton.Click += closeButton_Click;
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 폼 로드시 처리하기 - Form_Load(sender, e)
/// <summary>
/// 폼 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Load(object sender, EventArgs e)
{
Label[] cpuLabelArray = new Label[this.processorCount];
TrackBar[] trackBarArray = new TrackBar[this.processorCount];
GroupBox[] cpuGroupBoxArray = new GroupBox[this.processorCount];
for(int i = 0; i < this.processorCount; i++)
{
int yOffset = 20;
cpuGroupBoxArray[i] = new GroupBox();
cpuGroupBoxArray[i].Text = "CPU" + i.ToString();
cpuGroupBoxArray[i].Size = new Size(350, 50);
cpuGroupBoxArray[i].Location = new Point(20, i * 60 + 20);
RadioButton minimumRadioButton = new RadioButton();
RadioButton medianRadioButton = new RadioButton();
RadioButton maximumRadioButton = new RadioButton();
cpuGroupBoxArray[i].Controls.Add(minimumRadioButton);
cpuGroupBoxArray[i].Controls.Add(medianRadioButton );
cpuGroupBoxArray[i].Controls.Add(maximumRadioButton);
minimumRadioButton.Text = "Minimum";
minimumRadioButton.AutoSize = true;
minimumRadioButton.Location = new Point(40, yOffset);
minimumRadioButton.Checked = true;
minimumRadioButton.Tag = i.ToString() + ",0";
minimumRadioButton.Click += radioButton_Click;
medianRadioButton.Text = "Medium";
medianRadioButton.AutoSize = true;
medianRadioButton.Location = new Point(130, yOffset);
medianRadioButton.Tag = i.ToString() + ",50";
medianRadioButton.Click += radioButton_Click;
maximumRadioButton.Text = "Maximum";
maximumRadioButton.AutoSize = true;
maximumRadioButton.Location = new Point(220, yOffset);
maximumRadioButton.Tag = i.ToString() + ",100";
maximumRadioButton.Click += radioButton_Click;
this.contentPanel.Controls.Add(cpuGroupBoxArray[i]);
}
this.cpuLoadHelper = new CPULoadHelper();
}
#endregion
#region 폼을 닫을 경우 처리하기 - Form_FormClosing(sender, e)
/// <summary>
/// 폼을 닫을 경우 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
this.cpuLoadHelper.Dispose();
}
#endregion
#region 라디오 버튼 클릭시 처리하기 - radioButton_Click(sender, e)
/// <summary>
/// 라디오 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void radioButton_Click(object sender, EventArgs e)
{
RadioButton radioButton = sender as RadioButton;
if(radioButton != null)
{
string valueList = radioButton.Tag.ToString();
string[] valueArray = valueList.Split(new char[] { ',' });
this.cpuLoadHelper.SetTargetCPUUsageRatio(int.Parse(valueArray[0]), int.Parse(valueArray[1]));
}
}
#endregion
#region 종료 버튼 클릭시 처리하기 - closeButton_Click(sender, e)
/// <summary>
/// 종료 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void closeButton_Click(object sender, EventArgs e)
{
Close();
}
#endregion
}
}
※ 테스트 결과 Windows 10 라이젠 CPU에서는 정상 작동하지 않았다.
728x90
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON] 방화벽 상태 구하기 (0) | 2018.12.23 |
---|---|
[C#/COMMON] 특수 기호 표시하기 (0) | 2018.12.23 |
[C#/COMMON] 메인보드 시리얼 번호/CPU ID 구하기 (0) | 2018.12.23 |
[C#/COMMON] OleDbEnumerator 클래스 : OLEDB 공급자 조회하기 (0) | 2018.12.23 |
[C#/COMMON] 정규식 사용하기 (0) | 2018.12.22 |
[C#/COMMON] 파스칼/카멜 표기법 사용하기 (0) | 2018.12.13 |
[C#/COMMON] Clipboard 클래스 : 데이터 포맷 구하기 (0) | 2018.12.11 |
[C#/COMMON] Clipboard 클래스 : 멀티 포맷 사용하기 (0) | 2018.12.11 |
[C#/COMMON] Clipboard 클래스 : 객체 사용하기 (0) | 2018.12.11 |
[C#/COMMON] 진수 변환하기 (0) | 2018.12.09 |
댓글을 달아 주세요