cpu和内存使用率需两次采样计算:cpu必须间隔≥1秒调用nextvalue()并丢弃首次值;内存应读取“\memory\available mbytes”并结合总物理内存算百分比,禁用gc.gettotalmemory(false)。

CPU 和内存使用率不能靠“一次读取”得到,这是最常踩的坑。尤其是 CPU,NextValue() 第一次调用永远返回 0,不等间隔直接取值,结果就是恒定 0% 或乱跳;内存则容易误用 GC.GetTotalMemory(false)——它只反映托管堆大小,和系统内存毫无关系。
PerformanceCounter 获取系统内存使用率的正确姿势
核心是两步:先读 "\Memory\Available MBytes",再结合总物理内存算百分比。Windows 性能计数器不直接提供“已用内存百分比”,因为“已用”定义模糊(commit?working set?page file?),而 Available MBytes 是明确、稳定、用户态可读的指标。
-
Available MBytes是当前空闲的物理内存(MB),单位固定,无需换算 - 总内存不能用
GC.GetTotalMemory(false)——那是 .NET 托管堆已分配字节数,和系统 RAM 完全无关 - 推荐用
Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory,轻量、准确、无需管理员权限 - 若不想引用
Microsoft.VisualBasic,可用 WMI 查询Win32_ComputerSystem.TotalPhysicalMemory,但启动稍慢、需添加System.Management引用
CPU 使用率必须“两次调用 + ≥1 秒间隔”才有效
PerformanceCounter("Processor", "% Processor Time", "_Total") 的设计机制决定了它本质是个“速率计数器”:内部记录的是上一秒内处理器非空闲时间占比,首次调用只是初始化快照,无意义。
- 第一次
NextValue()必须丢弃,哪怕只 Sleep 500ms,第二次结果也大概率不准 - 官方建议最小间隔为 1000ms;实测低于 800ms 时,
NextValue()返回值波动剧烈甚至负值 -
"_Total"表示所有逻辑处理器汇总,要单核数据得枚举"Processor(0)"、"Processor(1)"等实例名 - 计数器对象应复用,不要每秒 new 一个——创建开销大,且可能触发 Windows 计数器句柄泄漏
获取当前进程自身内存/CPU 占用的写法差异
类别名从 "Processor" / "Memory" 切换到 "Process",实例名不再是 "_Total",而是进程名(如 "devenv" 或 "MyApp")。
- CPU:用
PerformanceCounter("Process", "% Processor Time", processName),注意该值是“该进程占总 CPU 时间的百分比”,不是“该进程用了多少核”,所以即使单线程满载,峰值也接近 100% ÷ 逻辑核数 - 内存:推荐
"Working Set"(单位字节),对应任务管理器“内存(专用工作集)”列;避免用"Private Bytes"(含未提交页)或"Virtual Bytes"(含地址空间碎片) - 进程名需精确匹配:
Process.GetCurrentProcess().ProcessName可能带扩展名(如"MyApp.exe"),而计数器实例名通常不含.exe,建议用Process.GetCurrentProcess().MainModule?.ModuleName或手动截断
真正难的不是写对一行代码,而是理解 PerformanceCounter 不是传感器,而是 Windows 内置的采样引擎——它依赖前一时刻的状态,拒绝“瞬时快照”。漏掉 Sleep、错用实例名、混用内存概念,都会让数字看起来像在随机波动。别信第一次跑出来的结果,盯住第二秒之后的输出。










