通过PerformanceCounter统计程序异常数量:结果异常问题排查
解决PerformanceCounter统计.NET异常总数不符合预期的问题
我来帮你排查这个问题,你的代码里有几个容易忽略的点,导致计数器结果和预期不符:
核心问题分析
- 你只完成了
PerformanceCounter的初始化,但没有在抛出异常前后读取计数器的数值做对比,自然看不到异常抛出后的计数变化 - 使用
_Global_实例名称会统计当前机器上所有.NET进程的异常总数,很容易被其他进程的异常干扰,针对单个进程的统计才更准确 - 初始化计数器时只调用了
BeginInit(),缺少EndInit()调用,可能导致计数器没有完全就绪,无法正常读取数据
修正后的代码实现
using System; using System.Diagnostics; class Program { static void Main() { // 用using语句自动管理计数器资源 using (PerformanceCounter exceptionCounter = new PerformanceCounter()) { exceptionCounter.CategoryName = ".NET CLR Exceptions"; exceptionCounter.CounterName = "# of Exceps Thrown"; // 使用当前进程名称作为实例,只统计本程序的异常 exceptionCounter.InstanceName = Process.GetCurrentProcess().ProcessName; exceptionCounter.BeginInit(); exceptionCounter.EndInit(); // 必须调用完成初始化 // 记录抛出异常前的初始累计值 long initialCount = exceptionCounter.RawValue; Console.WriteLine($"初始异常累计计数: {initialCount}"); // 手动抛出5次异常 for (int i = 0; i < 5; i++) { try { throw new Exception(); } catch (Exception) { Console.WriteLine($"第{i+1}次异常已抛出并捕获"); } } // 记录抛出异常后的累计值,计算差值得到本次抛出的异常数 long finalCount = exceptionCounter.RawValue; Console.WriteLine($"最终异常累计计数: {finalCount}"); Console.WriteLine($"本次代码实际抛出异常数: {finalCount - initialCount}"); } } }
关键注意事项
- 优先使用进程实例:如果只关心当前程序的异常,用
Process.GetCurrentProcess().ProcessName作为实例名称,避免全局统计的干扰 - 完整的初始化流程:调用
BeginInit()后一定要搭配EndInit(),确保计数器完成配置并就绪 - 对比累计值差值:
RawValue是从进程启动到当前的累计异常数,只有对比初始值和最终值的差值,才能得到这段代码抛出的异常数量 - 资源自动释放:用
using包裹PerformanceCounter,避免资源泄漏
额外验证方式
如果还是有疑问,可以打开Windows自带的性能监视器(perfmon.exe),手动添加.NET CLR Exceptions分类下的# of Exceps Thrown计数器,选择你的进程实例,运行程序时实时观察数值变化,就能直观确认统计是否正确。
内容的提问来源于stack exchange,提问作者hensing1
相关产品推荐
相关产品推荐

