PerformanceCounter蛋痛的设计
在.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蛋痛的设计的更多相关文章
- 鸡和蛋的OO设计
一个题目:用类图表示出鸡和蛋的关系. 第一版: 第二版: 一个鸡可以下N个蛋,一个蛋可以浮出0或者1个鸡. 问题是公鸡不会下单,第三版:
- 关于变量参数的传递,python让人蛋痛的地方
def find_file(file_table): with open(file_table, 'r', encoding='utf-8') as read_f: line_dict = {} fo ...
- python蛋痛的依赖管理
java有maven 来统一管理项目依赖.初学python不久还没发现类似这样的工具.只有暂时用这个方法来手动操作了. 你可以用pip导出你的dependency: $ pip freeze > ...
- Swift 玩转 3D Touch 之 Peek & Pop
什么是3D Touch 3D Touch 是iOS9之后专为 iPhone6s 机型加入的新特性,这一新技术移植于 Mac Book 上的 ForceTouch 更准确地说应该是 ForceTouch ...
- 你真的知道HTML吗?
经过几次面试当中,被问及到最基础的东西,没想到回答不上来,有点蛋痛,今天特地的复习了一下!! 内容: 1.Doctype(文档类型)的作用是什么?有多少文档类型? 2.浏览器标准模式和怪异模式之间的区 ...
- 模块化的JavaScript开发的优势在哪里
如今模块化的 JavaScript 的开发越来越火热,无论是模块加载器还是优秀的 JavaScript 模块,都是层出不穷.既然这么火,肯定是有存在的理由,肯定是解决了某些实际问题.很多没接触过模块化 ...
- ThoughtWorks开发持续集成及部署利器:Go
持续集成及部署利器:Go Go是一款先进的持续集成和发布管理系统,由ThoughtWorks开发.(不要和Google的编程语言Go混淆了!)其前身为Cruise,是ThoughtWorks在做咨 ...
- 在网络通讯中应用Protobuf
在网络通讯中应用Protobuf Protobuf的设计非常适用于在网络通讯中的数据载体,它序列化出来的数据量少再加上以K-V的方式来存储数据,对消息的版本兼容性非常强:还有一个比较大的优点就是有着很 ...
- as3设计模式乱用之工厂模式
好久没写技术相关的日记了,一忙,二懒,三则被这单调的生活熏得没什么感悟. 其实这篇日记早就想写了,项目开发初期的时候,带学生.经常看到那种乱用设计模式的现象.一方面,公司面试人的时候喜欢问设计模式,另 ...
随机推荐
- vue 调用摄像头拍照以及获取相片本地路径(实测有效)
在学习这个的时候有一点前提:这是针对手机功能的,所以最重要的是要用手机进行实时调试 包含图片的增加和删除功能 <template> <div> <!--照片区域--> ...
- Linux从入门到放弃(为做一个开发+运维的全能性人才而奋斗)
Linux?听说是一个操作系统,好用吗?” “我也不知道呀,和windows有什么区别?我能在Linux上玩LOL吗” “别提了,我用过Linux,就是黑乎乎一个屏幕,鼠标也不能用,不停地的敲键盘,手 ...
- 展开被 SpringBoot 玩的日子 《 五 》 spring data jpa 的使用
在上篇文章< 展开被 SpringBoot 玩的日子 < 二 >WEB >中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring da ...
- 大数据 - Java基础:读取键盘输入的方法
Java中获取键盘输入值的三种方法 程序编写中,从键盘获取数据是一件非常普通又平常的事 C:scanf() C++:cin() C#:Read().ReadKey().ReadLine() Java没 ...
- 几个VB常见又内涵的错误
第一位内涵的就是:没有对象 找到对象,却发现是别人的对象 不能加载也不能卸载...这到底是什么对象 哈哈哈~
- go-mod 入门
Q群有人问go mod 问题,自己也忘了些.顺便再整理下. GO111MODULE可以设置为三个字符串值之一:off,on或auto(默认值). off 则go命令从不使用新模块支持.它查找vendo ...
- HTML入门10
目前,掌握了图像,视频和音频的嵌入,下面来谈iframe和embed.object嵌入网页, 嵌入简史,刚开始流行用嵌入框架然后不同部分显示i不同内容,可以解决下载速度慢时的问题: 慢慢的插件技术流行 ...
- promise的理解
为什么会有promise,他的作用是什么? promise主要是为了解决js中多个异步回调难以维护和控制的问题. 什么是promise? 从图中,我们可以看出,Promise是一个函数,这个函数上有在 ...
- C# 使用WinApi操作剪切板Clipboard
前言: 最近正好写一个程序,需要操作剪切板 功能很简单,只需要从剪切板内读取字符串,然后清空剪切板,然后再把字符串导入剪切板 我想当然的使用我最拿手的C#来完成这项工作,原因无他,因为.Net框架封装 ...
- java中int和integer