在.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++ Json解析CJsonObject的详细使用

    引用头文件: #include <string> #include <iostream> #include <fstream> #include <casse ...

  2. python3.5.2库getpass

    getpass的功能是:允许隐式的输入字符串 import getpass _username='vigossr' _password='haha' username=input('username: ...

  3. CentOS7部分调优命令

    一般CentOS的磁盘空间占用最大的就是日志文件,日志文件主要保存在./log目录里,因此通过以下命令可以检查目录的大小. du -ah --max-depth=1 du命令的一些常用参数: -a或- ...

  4. mac上安装iterm2的一些步骤记录

    1.首先到item官网上下载item   下载地址 http://iterm2.com/ 2.把iitem2设置为默认终端: 3.设置快速打开关闭的hotkey 我们这里设置为command + T键 ...

  5. typeScript 学习

    最近看了下typescript, 虽然说已经有很多人已经用到它了,但是我还是写写自己的feel咯:这里推荐学习链接 https://ts.xcatliu.com. 这个入门学习,我不好做评价,但是我自 ...

  6. 实战深度学习OpenCV(二):读取并播放本地或者摄像头的视频

    一.读取并播放的代码如下: #include "pch.h" #include <iostream> #include <opencv2/core/core.hp ...

  7. [Swift]LeetCode89. 格雷编码 | Gray Code

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  8. [Swift]LeetCode173. 二叉搜索树迭代器 | Binary Search Tree Iterator

    Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ro ...

  9. [Swift]LeetCode191. 位1的个数 | Number of 1 Bits

    Write a function that takes an unsigned integer and return the number of '1' bits it has (also known ...

  10. [Swift]LeetCode387. 字符串中的第一个唯一字符 | First Unique Character in a String

    Given a string, find the first non-repeating character in it and return it's index. If it doesn't ex ...