如何在C#中获取每个核心的CPU负载?

6

我该如何在C#中获取每个核心(四核心CPU)的CPU负载?

谢谢 :)


1
看到了,但那是全局负载,我需要每个核心的负载。 - Sugarel
我找到了它: http://www.codegain.com/articles/csharp/windowsforms/how-to-display-processor-usage-of-dual-core-processors.aspx - Sugarel
3个回答

8
你可以使用WMI或System.Diagnostics命名空间。从那里,你可以获取任何想要的性能计数器(但初始化需要1-1.5秒钟 - 读取值是可以的,只有初始化很慢)。
代码可能看起来像这样:
    using System.Diagnostics;

    public static Double Calculate(CounterSample oldSample, CounterSample newSample)
    {
        double difference = newSample.RawValue - oldSample.RawValue;
        double timeInterval = newSample.TimeStamp100nSec - oldSample.TimeStamp100nSec;
        if (timeInterval != 0) return 100*(1 - (difference/timeInterval));
        return 0;
    }

    static void Main()
    {
        var pc = new PerformanceCounter("Processor Information", "% Processor Time");
        var cat = new PerformanceCounterCategory("Processor Information");
        var instances = cat.GetInstanceNames();
        var cs = new Dictionary<string, CounterSample>();

        foreach (var s in instances)
        { 
            pc.InstanceName = s;
            cs.Add(s, pc.NextSample());
        }

        while (true)
        {
            foreach (var s in instances)
            {
                pc.InstanceName = s;
                Console.WriteLine("{0} - {1:f}", s, Calculate(cs[s], pc.NextSample()));
                cs[s] = pc.NextSample();
            }
            System.Threading.Thread.Sleep(500);
        }
    }

重要的是,你不能仅依赖于本地 .net 计算 100nsInverse 性能计数器(对我来说只返回 0 或 100 … 是 bug 吗?),但你必须自己计算,并且为此,你需要每个实例的上一次 CounterSamples 存档(实例代表一个核心或这些核心的总和)。
似乎有一个关于这些实例的命名约定:
0,0 - 第一个 CPU 的第一个内核 0,1 - 第一个 CPU 的第二个内核 0,_Total - 第一个 CPU 的总负载 _Total - 所有 CPU 的总负载
(未经验证 - 在进一步调查完成之前不建议依赖它)...

1
代码有问题,因为您提供的代码有时会给出负的CPU使用百分比。 - tigrou
NextValue() 函数从 NextSample() 函数计算结果。第一个结果为 0,第二个结果为 0 或 100%,第三个结果为实际值,因此 "只有 0 或 100" 不是错误。 - Soleil
@tigrou 同感。Calculate 是错误的。你可能想使用 GetValue() 而不是 GetSample(),然后再进行计算。 - Soleil

0

由于内核在操作系统中显示为单独的 CPU,因此您可以使用与多处理器机器中每个 CPU 的负载确定所使用的相同代码。其中一个示例(使用 C 语言)在这里。请注意,它使用 WMI,因此上面评论中链接的其他线程可能已经为您提供了大部分内容。


0
首先,您需要与核心数量相同的性能计数器(这需要时间,您可能希望在异步任务中完成此操作,或者它会阻止您的用户界面):
CoreCount= Environment.ProcessorCount;
CPUCounters = new PerformanceCounter[CoreCount];
for (var i = 0; i < CoreCount; i++)
    CPUCounters[i] = new PerformanceCounter("Processor", "% Processor Time", $"{i}");

然后您可以获取每个核心的使用情况值:

public float[] CoreUsage { get; set; } // feel free to implement inpc

public void Update() => CoreUsage = CPUCounters.Select(o => o.NextValue()).ToArray();

然而,您可能想要调用Update()三次:第一次您将始终获得0.0,然后第二次始终是0.0100.0,最后才是实际值。

NextValue()提供的是瞬时值,而不是随时间变化的平均值;如果您想要在1秒内获得平均值,可以使用RawValue并按此处所述计算平均值:PerformanceCounter.RawValue Property


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接