我需要在执行进程期间获取内存和CPU使用率(该进程有时可以运行超过30分钟)。与任务管理器的值相比,我能够获得可用RAM,但CPU使用率不正确。难道我做错了什么?这是我的代码:
class Program
{
static List<float> AvailableCPU = new List<float>();
static List<float> AvailableRAM = new List<float>();
protected static PerformanceCounter cpuCounter;
protected static PerformanceCounter ramCounter;
static void Main(string[] args)
{
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
try
{
System.Timers.Timer t = new System.Timers.Timer(1200);
t.Elapsed += new ElapsedEventHandler(TimerElapsed);
t.Start();
Thread.Sleep(10000);
}
catch (Exception e)
{
Console.WriteLine("catched exception");
}
Console.ReadLine();
}
public static void TimerElapsed(object source, ElapsedEventArgs e)
{
float cpu = cpuCounter.NextValue();
float ram = ramCounter.NextValue();
Console.WriteLine(string.Format("CPU Value: {0}, ram value: {1}", cpu, ram));
AvailableCPU.Add(cpu);
AvailableRAM.Add(ram);
}
}
但是当我运行程序时,这是打印到控制台的内容,与任务管理器的值进行比较:
我做错了什么?
答案 0 :(得分:9)
你的价值观没有错。
您看到与任务管理器返回的差异的原因是“CPU使用率”值是针对给定间隔计算的,即两次Protected Sub gvList_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvList.RowDataBound
Dim j As Integer = 0
If e.Row.RowType == DataControlRowType.DataRow Then
// Find the button
Dim totalButton As LinkButton = DirectCast(e.Row.FindControl("lnkEdit"), LinkButton)
arrTotalPage(j) += Convert.ToDecimal(totalButton.Text)
End If
End Sub
次调用之间的值。如果任务管理器“不调用它自己的NextValue”(如果我们简化它的工作原理),你将不会返回相同的结果。
想象一下以下场景:
NextValue()
您可以尝试生成自己应用程序的多个进程,还应该看到不同的结果。
答案 1 :(得分:8)
以下是我发现的内容:我为每个核心创建了一个包含PerformanceCounter
个对象的列表,我添加百分比并将结果除以数据核心数量:
class Program
{
static List<float> AvailableCPU = new List<float>();
static List<float> AvailableRAM = new List<float>();
protected static PerformanceCounter cpuCounter;
protected static PerformanceCounter ramCounter;
static List<PerformanceCounter> cpuCounters = new List<PerformanceCounter>();
static int cores = 0;
static void Main(string[] args)
{
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
{
cores = cores + int.Parse(item["NumberOfCores"].ToString());
}
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
int procCount = System.Environment.ProcessorCount;
for(int i = 0; i < procCount; i++)
{
System.Diagnostics.PerformanceCounter pc = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", i.ToString());
cpuCounters.Add(pc);
}
Thread c = new Thread(ConsumeCPU);
c.IsBackground = true;
c.Start();
try
{
System.Timers.Timer t = new System.Timers.Timer(1200);
t.Elapsed += new ElapsedEventHandler(TimerElapsed);
t.Start();
Thread.Sleep(10000);
}
catch (Exception e)
{
Console.WriteLine("catched exception");
}
Console.ReadLine();
}
public static void ConsumeCPU()
{
int percentage = 60;
if (percentage < 0 || percentage > 100)
throw new ArgumentException("percentage");
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
// Make the loop go on for "percentage" milliseconds then sleep the
// remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
if (watch.ElapsedMilliseconds > percentage)
{
Thread.Sleep(100 - percentage);
watch.Reset();
watch.Start();
}
}
}
public static void TimerElapsed(object source, ElapsedEventArgs e)
{
float cpu = cpuCounter.NextValue();
float sum = 0;
foreach(PerformanceCounter c in cpuCounters)
{
sum = sum + c.NextValue();
}
sum = sum / (cores);
float ram = ramCounter.NextValue();
Console.WriteLine(string.Format("CPU Value 1: {0}, cpu value 2: {1} ,ram value: {2}", sum, cpu, ram));
AvailableCPU.Add(sum);
AvailableRAM.Add(ram);
}
}
以下是结果的截图(如您所见,第一种方法更精确):