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

C#中PerformanceCounter获取IIS站点Requests/Sec值不更新问题

解决PerformanceCounter获取ASP.NET Apps计数器不更新的问题

嘿,我懂你遇到的糟心事——之前用PerformanceCounter都好好的,偏偏拿特定IIS站点的"Requests/Sec"时,数据死活不更新,但性能监视器里明明显示正常,而且程序已经有管理员权限了对吧?咱们一步步捋清楚问题出在哪:

问题排查与修复步骤

1. 实例名称匹配的大小写坑

先看你代码里的这段:

cat.GetInstanceNames().First(s => s.Contains("_lm_w3svc_3_root").ToUpper())

这里的.ToUpper()放错地方啦!你是把Contains的结果(true/false)转成大写,而不是把实例名称s转成大写来匹配。IIS生成的计数器实例名通常是大写的_LM_W3SVC_3_ROOT,大小写不匹配的话,你可能拿到了错误的实例,自然拿不到正确的更新数据。改成这样才对:

cat.GetInstanceNames().First(s => s.ToUpper().Contains("_LM_W3SVC_3_ROOT"))

或者更严谨的不区分大小写比较:

cat.GetInstanceNames().First(s => s.Equals("_LM_W3SVC_3_ROOT", StringComparison.OrdinalIgnoreCase))

2. 别每次都新建PerformanceCounter实例!

这是最常见的坑——PerformanceCounter的NextValue()方法第一次调用永远返回0,因为它需要两次采样来计算差值(比如每秒请求数是两次采样的差除以时间间隔)。你每次调用GetRequest()都新建一个计数器实例,每次调用NextValue()都是第一次,当然拿不到更新的数据!

正确的做法是把计数器实例做成静态的,在程序启动时初始化一次,后续复用它:

// 静态字段保存计数器实例,只初始化一次
private static readonly PerformanceCounter _requestCounter;

// 在类的静态构造函数里初始化计数器
static YourClassName()
{
    var cat = PerformanceCounterCategory.GetCategories()
        .FirstOrDefault(s => s.CategoryName.Contains("ASP.NET Apps v4.0.30319"));
    if (cat == null)
        throw new InvalidOperationException("找不到ASP.NET Apps v4.0.30319计数器类别");
    
    var instanceName = cat.GetInstanceNames()
        .First(s => s.Equals("_LM_W3SVC_3_ROOT", StringComparison.OrdinalIgnoreCase));
    
    _requestCounter = new PerformanceCounter(
        "ASP.NET Apps v4.0.30319", 
        "Requests/Sec", 
        instanceName, 
        true);
    
    // 第一次调用NextValue()做初始化,返回0,后续调用才会拿到真实的计算值
    _requestCounter.NextValue();
}

public static int GetRequest()
{
    // 复用已初始化的计数器,每次调用NextValue()都会返回最新的计算值
    return unchecked((int)_requestCounter.NextValue());
}

3. 先确认你要的实例真的存在

有时候IIS站点重启、应用池回收后,计数器实例名可能会变,你可以先把所有实例名打印出来,确认你要的那个确实在列表里:

var cat = PerformanceCounterCategory.GetCategories()
    .First(s => s.CategoryName.Contains("ASP.NET Apps v4.0.30319"));
foreach (var instance in cat.GetInstanceNames())
{
    Console.WriteLine($"找到实例:{instance}");
}

这样能避免你选到错误的实例,白忙活一场。

4. 权限兜底检查

虽然你说程序有管理员权限,但还是确认下:运行程序的用户是否在Performance Monitor Users组里?不过既然性能监视器能正常读取,这个概率不高,但排查的时候可以顺便确认下,排除权限问题。

总结

最可能的两个原因就是:每次新建计数器实例导致NextValue()永远返回初始0,以及实例名称大小写匹配错误。按照上面的步骤调整代码,复用计数器实例,修正匹配逻辑,应该就能拿到实时更新的请求数了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:26:47