博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PerformanceCounter蛋痛的设计
阅读量:6340 次
发布时间:2019-06-22

本文共 2943 字,大约阅读时间需要 9 分钟。

在.NET下对进程的性能计数可以使用PerformanceCounter,通过该对象可以对进程的CPU,内存等信息进行统计.对于正常使用来说这个对象还是很方便,但对于同一名称的多个进程进行性能计数那真是可以无比蛋痛...详细说一下PerformanceCounter对多个同一名称的进程计数所面对的问题.

应用情况

PerformanceCounter是通过进程实例名来监控计数,但这个实例名是操作系统实时动态分配的,如果同一名称的进程只有一个那就比较好处理.如果同一名称的进程有多个那悲剧的事情就来的,随着同一名称的进程创建和关闭会影响到其他同一名称进程的实例名.这样会导致相应的PerformanceCounter和进程的对应关系完全错乱...(真是无法理解.NET对这个的实现为什么不用PID)

假设现在有个ams-p.exe应用程序,依次分别打开三次,那对应的进程实例名是:

1)ams-p.exe [pid:7012]

2)ams-p.exe#1 [pid:7013]

3)ams-p.exe#2 [pid:7014]

由于实例名windows系统实时分配的,一旦同一名称的进程数量发现变化那对应进程的实例名也会变.针对上面情况当2被关闭后那实例对应的关系可以是.

1)ams-p.exe [pid:7012]

3)ams-p.exe#1 [pid:7014]

这样就会导致3对应的实例名不存在,从而导致PerformanceCounter上的统计错误,如果对应同一名称的进程数量更多,中间其中一个进程关闭那就会有大量的PerformanceCounter统计和进程对应关系就都会存在错误的.

解决办法

虽然有解决方法,但做法都是非常蛋痛的,监控Process的Exite事件然后根据退出情况来调整实例名和PID的对应关系,不过这种方式是存在一些问题,如果其他应用也是这个进程名又是通过其他渠道打开你未及时捕抓绑定Exite事件,那就会导致计数错误的悲剧事件发生.而另一种解决方法就比较全面点,在执行所有PerformanceCounter前行把当前系统该名称的进程信息获取上载并建立一个实时的实例名和PID对应关系,然后在执行PerformanceCounter后记录对应实例名的PID计数情况.具体代码如下:

class CPUCounter:IDisposable    {        public CPUCounter(string processName)        {            mProcessName = processName;            mTimer = new System.Threading.Timer(GetUsage, null, 1000, 1000);        }        private System.Threading.Timer mTimer;        private string mProcessName;        private Dictionary
mProcessCpuUsage = new Dictionary
(); private List
mCounters = new List
(); private Dictionary
mProcessIDs = new Dictionary
(); public float ProcessUsage(int pid) { float result = 0; mProcessCpuUsage.TryGetValue(pid, out result); return result; } private void OnCreateCounter(string processname) { CounterItem item = mCounters.Find(e => e.ProcessName == processname); if (item == null) { item = new CounterItem(); item.Counter = new PerformanceCounter(); item.Counter.CategoryName = "Processor"; item.Counter.CounterName = "% Processor Time"; item.Counter.InstanceName = processname; } item.Enabled = true; } private void GetUsage(object state) { mProcessIDs.Clear(); Process[] ps = Process.GetProcessesByName(mProcessName); List
disposeditems = new List
(); if (ps.Length == 1) { mProcessIDs.Add(mProcessName, ps[0].Id); OnCreateCounter(mProcessName); } else { for (int i = 1; i < ps.Length; i++) { mProcessIDs.Add(mProcessName + "#" + i, ps[i].Id); OnCreateCounter(mProcessName + "#" + i); } } foreach (CounterItem item in mCounters) { if (item.Enabled) { mProcessCpuUsage[mProcessIDs[item.ProcessName]] = item.Counter.NextValue(); item.Enabled = false; } else { disposeditems.Add(item); } } if(disposeditems.Count>0) foreach (CounterItem item in disposeditems) { mCounters.Remove(item); } } class CounterItem { public string ProcessName { get; set; } public System.Diagnostics.PerformanceCounter Counter { get; set; } public bool Enabled { get; set; } } public void Dispose() { if (mTimer != null) mTimer.Dispose(); } }

 如果有更好办法的同学不防分享一下.

转载地址:http://snhoa.baihongyu.com/

你可能感兴趣的文章
04-【MongoDB入门教程】mongo命令行
查看>>
字符串与整数之间的转换
查看>>
断点传输HTTP和URL协议
查看>>
redis 数据类型详解 以及 redis适用场景场合
查看>>
mysql服务器的主从配置
查看>>
巧用AJAX技术,通过updatePanel控件实现局部刷新
查看>>
20140420技术交流活动总结
查看>>
SaltStack配置salt-api
查看>>
各种情况下block的类型
查看>>
ThinkPHP 3.2.x 集成极光推送指北
查看>>
js作用域链
查看>>
java中如何选择Collection Class--java线程(第3版)
查看>>
为运维人员插上腾飞更远的翅膀!
查看>>
Word 2003中编辑标记与格式标记大讨论
查看>>
Android系统的开机画面显示过程分析(6)
查看>>
vivo Hi-Fi+QQ音乐 数字音乐市场的一剂良方
查看>>
Cocos2d-x 3.2 异步动态加载 -- 保卫萝卜开发总结
查看>>
聚焦触宝反侵权事件:中国创业者用什么护航海外市场大门
查看>>
AOP技术基础
查看>>
Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(2)
查看>>