在C#程序中,我试图获取应用程序的CPU使用百分比,但它总是显示100

时间:2012-07-12 20:32:54

标签: c# visual-studio-2010 performancecounter

这是我的代码。

        PerformanceCounter cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";

        // will always start at 0
        dynamic firstValue = cpuCounter.NextValue();
        System.Threading.Thread.Sleep(1000);


        dynamic secondValue = cpuCounter.NextValue();
        return secondValue;

这里有很多人遇到的问题是这个问题归零,但是我总是得到100,而且我确信我的软件并没有占用那么多的CPU粉末。关于我能做些什么来使这项工作正确的任何想法。为了清楚起见,我试图从运行此代码的应用程序中检索处理器使用情况,而不是单独的代码。我也在VM上运行,但这似乎并不重要。有什么想法吗?

2 个答案:

答案 0 :(得分:13)

它有助于理解cpu如何解决为什么会发生这种情况。通过谈论只有一个核心的cpu,我会稍微简化它,对于具有多个核心的CPU,故事不会改变。

当cpu核未处于睡眠模式时,它只能处于两种不同的状态。它要么执行代码,要尽可能快地运行完全执行指令。或者它没有执行代码,因为不需要做任何事情。在这种情况下,它是物理关闭。执行HLT指令时会发生这种情况。停止,什么也不做,不消耗电力。

只有一种方法可以使处理器从Halt状态恢复,需要一个中断。这是芯片上的物理引脚,该引脚上的电压使其恢复活跃。该电压由中断控制器产生,中断控制器是另一个芯片,它从机器的各个部分接收请求以使cpu做一些有用的事情。

该中断的最重要来源是时钟。它以0.0156秒的速度运行,每秒使cpu恢复活动64次。这会在操作系统中激活一段基本上检查两件事的代码。 “当我睡着的时候发生了什么事?”并且“我根本没有睡着,有时间去做其他重要的事情”。或者换句话说,它不仅会使cpu保持活动状态,而且还会中断它正在执行的操作。因此信号的名称。

时钟不是唯一的中断源,你有其他硬件连接到cpu。 I / O设备。任何机器都有的重要部件是磁盘控制器,光驱控制器,网卡,鼠标和键盘。以及您在Device Manager小程序中看到的任何其他内容。它们是具有自己的小处理器的子系统,可以处理东西。告诉主cpu他们已经完成了。因此,等待结果的机器上的任何线程都可以使用提供的数据继续执行。

绝大多数时候,你坐在你旁边的那台个人电脑没有做任何重要事情。比方说,等着你读这个答案。由视频适配器和LCD显示器处理的东西,cpu没有帮助。你可以在TaskMgr.exe中看到它,cpu利用率在0左右徘徊。你移动鼠标,点击滚动条来读取这个(长)答案,然后发生了一些事情。鼠标生成一个中断,它通过几层软件传递,最终告诉浏览器滚动视图。这需要大约几毫秒,给予或采取。

几毫秒的工作,cpu在它之后就睡着了。所以,当你向性能计数器询问cpu时,“你最近做了多少工作”,它会说:“好吧,我花了几毫秒的时间来刻录核心,然后不再更新你的屏幕。但不,其他而不是我在豌豆上睡觉“

重要的是你经常提出的问题。样板方式是Perfmon使用的方式。每隔一秒,它就会问“你做了什么”。并且处理器会说:“好吧,在最后一秒我执行了20毫秒的有用工作。剩下的时间我死了世界,没什么用处”。因此任务管理器显示2%。

现在让我们按照你的方式去做吧。你要求perf计数器值,然后在一个纳秒之后再次要求它。处理器会说:“好吧,我返回了一个性能计数器值并试图重新入睡。没有工作,程序一直运行代码并问我同样的事情!”。

因此结果是准确的,处理器被您的请求占用,您没有给它机会关闭。 Cpu利用率为100%。

解决方案:像Perfmon那样做。用计时器询问第二次。缩短时间,数字上下变快。让它太短,它将是100%

答案 1 :(得分:2)

这里的内容类似于您可能尝试的内容

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

cpuCounter = new PerformanceCounter();

cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";

ramCounter = new PerformanceCounter("Memory", "Available MBytes");


public string getCurrentCpuUsage(){
            return cpuCounter.NextValue()+"%";
}

public string getAvailableRAM(){
            return ramCounter.NextValue()+"MB";
}