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

Ali*_*ioo 13 c# performancecounter visual-studio-2010

这是我的代码.

        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;
Run Code Online (Sandbox Code Playgroud)

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

Han*_*ant 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%


Met*_*Man 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";
} 
Run Code Online (Sandbox Code Playgroud)