PerformanceCounter CPU和内存,如任务管理器

kof*_*fus 7 c# performancecounter

我正在尝试监视CPU和内存,并获得与TaskManager值匹配的值(或尽可能接近).到目前为止,我有:

static readonly PerformanceCounter IdleCounter = new PerformanceCounter("Processor", "% Idle Time", "_Total");
static readonly PerformanceCounter RamCounter = new PerformanceCounter("Memory", "Available MBytes");

public string f() {
  return "cpu: " + (100-IdleCounter.NextValue()) + " , ram: " + RamCounter.NextValue() + "MB";
}
Run Code Online (Sandbox Code Playgroud)

这给了cpu非常准确(与incManager比较)的值,尽管如果可能我想更接近.

对于内存,但它似乎不匹配,我得到一个数字,但我真正想要的是百分比像任务管理器显示..

有帮助吗?

Han*_*ant 2

   public string f()
Run Code Online (Sandbox Code Playgroud)

最重要的事情是以与任务管理器相同的速率对这些性能计数器进行采样。特别是对于% Idle Time,一个粒度为 1/64 秒的数字。请务必使用 Timer 或 DispatcherTimer,将其 Interval 设置为 1000。

  ... new PerformanceCounter("Processor", "% Idle Time", "_Total")
Run Code Online (Sandbox Code Playgroud)

您需要使用不同的计数器,类别“处理器信息”。该计数器使用略有不同的策略来测量性能,它试图补偿超线程核心的不平等行为以及处理器时钟频率限制的副作用。在我的机器上差异约为 4%。请注意,很难获得精确的匹配,数字变化很快,并且您只是偶然与任务管理器的采样时间完全同步。

  ... new PerformanceCounter("Memory", "Available MBytes")
Run Code Online (Sandbox Code Playgroud)

要将其转换为百分比,您需要从可用物理 RAM 总量中减去该数字。您可以从ComputerInfo.TotalPhysicalMemory获取此数字,如本文所示。如果您不想使用这个命名空间(常见的抱怨),那么您必须pinvoke GlobalMemoryStatusEx()

我用来验证这些更改的代码:

private void timer1_Tick(object sender, EventArgs e) {
    label1.Text = IdleCounter.NextValue().ToString("N0");
    double total = new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;
    var used = 1024.0 * 1024.0 * RamCounter.NextValue();
    label2.Text = (100.0 * (total - used) / total).ToString("N0");
}
Run Code Online (Sandbox Code Playgroud)