试图拉动CPU&性能监视器中的网络使用信息

时间:2018-06-12 15:12:40

标签: c# performancecounter

我正在尝试从进程中获取CPU和网络使用信息。
在我的示例中,我将使用进程chrome

这是我如何调用使用IEnumerable<String>

的方法
foreach (string p in GetProcessStatistics(new string[] { "chrome" }))
{
  Console.WriteLine(p);
}

这是方法。

    private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
    {
        Process[] processList = Process.GetProcesses();

        foreach (string process in processesTosearch)
        {
            foreach (Process p in processList)
            {
                if (p.ProcessName == process)
                {
                    StringBuilder sb = new StringBuilder();
                    PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
                    double cpuData = CPUperformanceCounter.NextValue();
                    PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);
                    double networkData = NETWORKperformanceCounter.NextValue();

                    sb.AppendLine("ID: " + p.Id.ToString());
                    sb.AppendLine("NAME: " + p.ProcessName);
                    sb.AppendLine("CPU USAGE: " + cpuData);
                    sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
                    sb.AppendLine("NETWORK USAGE: " + networkData);
                    yield return sb.ToString();
                }
            }
        }
    }

以下是其中一个结果的输出

ID: 17624
NAME: chrome
CPU USAGE: 0
RAM USAGE: 23.2MB
NETWORK USAGE: 0

当我查看性能监视器时,cpu和网络值不是0,但是在控制台中,它们是。

我从一些研究中了解到价值永远不会是完美的,但为什么他们在控制台应用程序中显示0而不是在性能监视器上显示?

2 个答案:

答案 0 :(得分:2)

每个计数器至少需要两次读取,至少间隔一秒才能获得可用的读数。

根据需要重新排列,但您需要执行以下操作:

private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
{
    Process[] processList = Process.GetProcesses();

    foreach (string process in processesTosearch)
    {
        foreach (Process p in processList)
        {
            if (p.ProcessName == process)
            {
                StringBuilder sb = new StringBuilder();
                PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
                PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);

                // set a baseline
                CPUperformanceCounter.NextValue();
                NETWORKperformanceCounter.NextValue();

                Thread.Sleep(1000);

                double cpuData = CPUperformanceCounter.NextValue();
                double networkData = NETWORKperformanceCounter.NextValue();

                sb.AppendLine("ID: " + p.Id.ToString());
                sb.AppendLine("NAME: " + p.ProcessName);
                sb.AppendLine("CPU USAGE: " + cpuData);
                sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
                sb.AppendLine("NETWORK USAGE: " + networkData);
                yield return sb.ToString();
            }
        }
    }
}

答案 1 :(得分:1)

我喜欢杰夫的解决方案,但对我来说我想要一个平均水平。在获得CPU利用率方面存在一些问题,似乎应该解决一个简单的程序包,但我没有看到。

第一个当然是第一个请求的值为0是无用的。既然您已经知道第一个响应为0,那么为什么函数不将其考虑在内并返回true .NextValue()?

第二个问题是,当试图确定应用可能会由于峰值或两次峰值之间的可用资源而做出决策时,可能会瞬间获取瞬时读数。

我的解决方案是执行一个for循环,该循环循环并为您提供过去几秒钟的平均值。您可以调整计数器以使其变短或变长(只要大于2)。

public static float ProcessorUtilization;

public static float GetAverageCPU()
{
    PerformanceCounter cpuCounter = new PerformanceCounter("Process", "% Processor Time", Process.GetCurrentProcess().ProcessName);
    for (int i = 0; i < 11; ++i)
    {
        ProcessorUtilization += (cpuCounter.NextValue() / Environment.ProcessorCount);
    }
    // Remember the first value is 0, so we don't want to average that in.
    Console.Writeline(ProcessorUtilization / 10); 
    return ProcessorUtilization / 10;
}