在.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<int, float> mProcessCpuUsage = new Dictionary<int, float>(); private List<CounterItem> mCounters = new List<CounterItem>(); private Dictionary<string, int> mProcessIDs = new Dictionary<string, int>(); 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<CounterItem> disposeditems = new List<CounterItem>();
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();
}
}

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

PerformanceCounter蛋痛的设计的更多相关文章

  1. 鸡和蛋的OO设计

    一个题目:用类图表示出鸡和蛋的关系. 第一版: 第二版: 一个鸡可以下N个蛋,一个蛋可以浮出0或者1个鸡. 问题是公鸡不会下单,第三版:

  2. 关于变量参数的传递,python让人蛋痛的地方

    def find_file(file_table): with open(file_table, 'r', encoding='utf-8') as read_f: line_dict = {} fo ...

  3. python蛋痛的依赖管理

    java有maven 来统一管理项目依赖.初学python不久还没发现类似这样的工具.只有暂时用这个方法来手动操作了. 你可以用pip导出你的dependency: $ pip freeze > ...

  4. Swift 玩转 3D Touch 之 Peek & Pop

    什么是3D Touch 3D Touch 是iOS9之后专为 iPhone6s 机型加入的新特性,这一新技术移植于 Mac Book 上的 ForceTouch 更准确地说应该是 ForceTouch ...

  5. 你真的知道HTML吗?

    经过几次面试当中,被问及到最基础的东西,没想到回答不上来,有点蛋痛,今天特地的复习了一下!! 内容: 1.Doctype(文档类型)的作用是什么?有多少文档类型? 2.浏览器标准模式和怪异模式之间的区 ...

  6. 模块化的JavaScript开发的优势在哪里

    如今模块化的 JavaScript 的开发越来越火热,无论是模块加载器还是优秀的 JavaScript 模块,都是层出不穷.既然这么火,肯定是有存在的理由,肯定是解决了某些实际问题.很多没接触过模块化 ...

  7. ThoughtWorks开发持续集成及部署利器:Go

    持续集成及部署利器:Go   Go是一款先进的持续集成和发布管理系统,由ThoughtWorks开发.(不要和Google的编程语言Go混淆了!)其前身为Cruise,是ThoughtWorks在做咨 ...

  8. 在网络通讯中应用Protobuf

    在网络通讯中应用Protobuf Protobuf的设计非常适用于在网络通讯中的数据载体,它序列化出来的数据量少再加上以K-V的方式来存储数据,对消息的版本兼容性非常强:还有一个比较大的优点就是有着很 ...

  9. as3设计模式乱用之工厂模式

    好久没写技术相关的日记了,一忙,二懒,三则被这单调的生活熏得没什么感悟. 其实这篇日记早就想写了,项目开发初期的时候,带学生.经常看到那种乱用设计模式的现象.一方面,公司面试人的时候喜欢问设计模式,另 ...

随机推荐

  1. 【C语言编程练习】5.12 兔子产仔问题

    1. 题目要求 把一对新生的兔子关在屋子里,已知一对两个月大的兔子以后买一个月可以生一对小兔子,而这一对心生的小兔子初生两个月以后才可以生小兔子,假如一年内没有死亡,一年可以繁殖成多少对? 2. 题目 ...

  2. 我的 FPGA 学习历程(01)—— FPGA 基础知识和 Quartus 的安装

    高级的嵌入式市场主要分为以下三类:ARM.DSP 和 FPGA. 其中 ARM 是行业内的佼佼者,目前几乎所有的安卓智能手机都使用 ARM 授权的 CPU架构:而 DSP(数字信号处理器) 早年就被大 ...

  3. BZOJ3497 : Pa2009 Circular Game

    令先手为$A$,后手为$B$,将相邻同色棋子合并成块,首先特判一些情况: 如果所有格子都是满的,那么显然$A$必败. 否则如果所有块都只有一个棋子,那么显然平局. 枚举$A$的第一步操作,如果可以使得 ...

  4. 最好的前端API备忘单整理

    注:这份表引自The best front-end hacking cheatsheets - all in one place Javascript ES2015 Cheatsheet JavaSc ...

  5. 马昕璐201771010118 《面对对象程序设计(java)》第九周学习总结

    第一部分:理论知识学习部分 异常:在程序的执行过程中所发生的异常事件,它中断指令的正常执行. Java把程序运行时可能遇到的错误分为两类: 非致命异常:通过某种修正后程序还能继续执行. 致命异常:程序 ...

  6. Redis sentinel 哨兵模式

    一.sentinel介绍 Sentinel作用: 1):Master状态检测 2):如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Maste ...

  7. aarch64的架构:unrecognized command line option '-mfpu=neon'

    不用添加这个'-mfpu=neon'的编译器选项了,因为这个架构下neon是默认启动的. 参考: https://lists.linaro.org/pipermail/linaro-toolchain ...

  8. python语法_装饰器

    装饰器的知识点储备: 1 作用域 2 高阶函数 3 闭包 内部函数,对外部作用作用域的变量进行了引用,该内部函数就认为是闭包, def outer(): x=10 def inner(): print ...

  9. 【面试篇】资深招聘HR有哪些面试技巧?

    15年资深招聘HR总结的面试技巧     1.做一下自我介绍 了解应聘者的基本信息和工作经历 2.以往工作中您的职责是什么? 了解应聘者的相关工作经验和其系统性全面性 3.请讲一下您以往的工作经历. ...

  10. [Swift]LeetCode796. 旋转字符串 | Rotate String

    We are given two strings, A and B. A shift on A consists of taking string A and moving the leftmost ...