You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 8 Web API获取与任务管理器一致的CPU、RAM使用率

.NET Core 8 Web API 准确获取CPU和RAM使用率(匹配任务管理器数值)

问题

在.NET Core 8 Web API中尝试获取某一时刻的CPU和RAM使用率百分比,目前RAM数值与任务管理器接近,但CPU使用率偏差较大。原有代码如下:

public async Task<void> getCpuUsageData()
{
    try
    {
        var CpuThreadSleepTime = _appSettings.ThreadSleepTimeForCPU; // CpuThreadSleepTime - 30000
        var RamThreadSleepTime = _appSettings.ThreadSleepTimeForRAM; // RamThreadSleepTime - 30000
        var totalMemory = GetTotalPhysicalMemory();
        var totalCpu = GetTotalCpu();
        var ramCounter = new PerformanceCounter("Memory", "Available MBytes");
        var availableMemory = ramCounter.NextValue();
        var usedMemory = totalMemory - availableMemory;
        var usedMemoryPercentage = (usedMemory / totalMemory) * 100;
        var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
        cpuCounter.NextValue();
        Thread.Sleep(CpuThreadSleepTime);
        var cpuUsagePercentage = cpuCounter.NextValue();
        var usedCpu = totalCpu - cpuUsagePercentage;
        var usedCpuPercentage = (usedCpu / totalCpu) * 100;

        Console.WriteLine("Used Ram Percentage : " + usedMemoryPercentage);
        Console.WriteLine("Used CPU Percentage : " + usedCpuPercentage);

    }
    catch (Exception ex)
    {
        throw ex;
    }
}


public float GetTotalPhysicalMemory()
{
    try
    {
        float totalMemory = 0;
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem");
        foreach (ManagementObject mo in searcher.Get())
        {
            totalMemory = Convert.ToSingle(mo["TotalPhysicalMemory"]) / (1024 * 1024); // Convert bytes to MB
        }
        return totalMemory;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

public float GetTotalCpu()
{
    try
    {
        int totalCpu = 0;
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT NumberOfLogicalProcessors FROM Win32_Processor");
        foreach (ManagementObject mo in searcher.Get())
        {
            totalCpu += Convert.ToInt32(mo["NumberOfLogicalProcessors"]);
        }
        return (float)totalCpu;
    }
    catch (Exception ex)
    {
        throw ex;
    }

}

问题分析

  1. CPU计算逻辑错误:Processor计数器的% Processor Time(_Total实例)返回的就是所有逻辑核心的总使用率百分比(范围0-100),不需要用逻辑核心数做减法运算,原有代码的usedCpu = totalCpu - cpuUsagePercentage完全不符合逻辑。
  2. 采样间隔过长:任务管理器的CPU使用率是取最近1-2秒的平均值,原有代码休眠30秒会导致采样的是30秒前的使用率,偏差极大。
  3. 异步方法使用不当:async Task<void>应改为async Task,且用await Task.Delay()替代Thread.Sleep()避免阻塞线程池线程。
  4. 内存计算可优化:可以直接使用Memory计数器的% Committed Bytes In Use获取内存使用率,无需手动计算。

修正后的代码

using System.Diagnostics;
using System.Management;

public async Task GetSystemUsageData()
{
    try
    {
        // 内存使用率获取(与任务管理器匹配)
        using var ramCounter = new PerformanceCounter("Memory", "% Committed Bytes In Use");
        var usedMemoryPercentage = ramCounter.NextValue();
        // 首次获取可能为0,需等待短时间再取一次
        await Task.Delay(100);
        usedMemoryPercentage = ramCounter.NextValue();

        // CPU使用率获取(与任务管理器匹配)
        using var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
        // 首次调用NextValue()返回0,需触发采样
        cpuCounter.NextValue();
        // 等待100ms获取有效采样(匹配任务管理器的短周期平均)
        await Task.Delay(100);
        var usedCpuPercentage = cpuCounter.NextValue();

        // 输出结果
        Console.WriteLine($"Used Ram Percentage : {Math.Round(usedMemoryPercentage, 1)}%");
        Console.WriteLine($"Used CPU Percentage : {Math.Round(usedCpuPercentage, 1)}%");
    }
    catch (Exception ex)
    {
        // 建议添加日志而非直接抛出,此处保留原有逻辑
        throw ex;
    }
}

// 如需获取总内存大小,可保留此方法(可选)
public float GetTotalPhysicalMemory()
{
    using var searcher = new ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem");
    foreach (ManagementObject mo in searcher.Get())
    {
        return Convert.ToSingle(mo["TotalPhysicalMemory"]) / (1024 * 1024 * 1024); // 转换为GB更直观
    }
    return 0;
}

关键说明

  1. CPU采样逻辑:% Processor Time的_Total实例直接返回总CPU使用率,无需额外计算。两次NextValue()间隔100ms,符合任务管理器的采样周期,数值会高度匹配。
  2. 内存采样:% Committed Bytes In Use直接对应任务管理器中“内存”选项卡的“已提交”百分比,和任务管理器显示一致。
  3. 资源释放:使用using语句自动释放PerformanceCounter和ManagementObjectSearcher资源,避免内存泄漏。
  4. 异步优化:用await Task.Delay()替代Thread.Sleep(),不会阻塞Web API的线程池线程,更符合异步编程规范。

内容的提问来源于stack exchange,提问作者Selaka Nanayakkara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:57:32