获取电脑实时CPU使用率

摘要:
=ERROR_ SUCCESS)15{16pItemDlg-˃MessageBox;17continue;18}1920//将计数器21HCOUNTER计数器添加到查询中;22//计数器=GlobalAlloc;23status=PdhAddCounter;24if(状态!

要求:实现一个计算电脑实时CPU占有率的测试程序,将多种方法获取结果显示在对话框上,动态显示。

实现:

1、新建基于对话框的MFC应用程序,Dialog上添加控件,为控件添加CSting类型变量m_RateResult1、m_RateResult2、m_RateResult3,

获取电脑实时CPU使用率第1张      

获取电脑实时CPU使用率第2张

2、创建线程类(Thread.h和Thread.cpp),在 ####Dlg.cpp 文件中的初始化函数 OnInitDialog() 中创建计算CPU利用率的线程

    // TODO: 在此添加额外的初始化代码

    _beginthread(&CThread::InitCalcuPdh, 0, this);
    _beginthread(&CThread::InitCalcuGet, 0, this);
    _beginthread(&CThread::InitCalcuNt,  0, this);

3、线程类中计算CPU利用率

方式一:使用Performance Data Helper(PDH)性能数据助手,获取CPU利用率

 1 void CThread::InitCalcuPdh(void *pDlg)
 2 {
 3     CCalculateCPURateDlg *pItemDlg = (CCalculateCPURateDlg *)pDlg;
 4     if (pItemDlg == NULL)
 5     {
 6         return;
 7     }
 8 
 9     while(1)
10     {
11         //打开查询(query)句柄
12         HQUERY query;
13         PDH_STATUS status = PdhOpenQuery(NULL, NULL, &query);
14         if (status != ERROR_SUCCESS)
15         {
16             pItemDlg->MessageBox(L"Open Query Error", NULL, MB_OK);
17             continue;
18         }
19             
20         //在查询中加入计数器(counter)
21         HCOUNTER counter;
22         //counter = (HCOUNTER *)GlobalAlloc(GPTR, sizeof(HCOUNTER));
23         status = PdhAddCounter(query, LPCWSTR(L"\Processor Information(_Total)\% Processor Time"), NULL, &counter);
24         if (status != ERROR_SUCCESS)
25         {
26             pItemDlg->MessageBox(L"Add Counter Error", NULL, MB_OK);
27             continue;
28         }
29 
30         //收集query的数据,在两条PdhCollectQueryData()语句之间加入一条Sleep(1000)语句
31         PdhCollectQueryData(query);
32         Sleep(1000);
33         PdhCollectQueryData(query);
34 
35         //获得格式化(可以显示的)数据
36         PDH_FMT_COUNTERVALUE pdhValue;
37         DWORD dwValue;
38         status = PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
39         if (status != ERROR_SUCCESS)
40         {
41             pItemDlg->MessageBox(L"Get Value Error", NULL, MB_OK);
42             continue;
43         }
44         pItemDlg->m_RateResult1.Format(L"%.0lf%%", pdhValue.doubleValue);
45 
46         SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE); 
47         PdhCloseQuery(query);
48     }
49 }

方式二:使用windows 自带的API(GetSystemTimes)获取CPU利用率

 1 __int64 DiffFileTime(FILETIME time1, FILETIME time2)
 2 {
 3     __int64 a = time1.dwHighDateTime << 32 | time1.dwLowDateTime;
 4     __int64 b = time2.dwHighDateTime << 32 | time2.dwLowDateTime;
 5     return (b - a);
 6 }
 7 void CThread::InitCalcuGet(void *pDlg)
 8 {
 9     CCalculateCPURateDlg *pItemDlg = (CCalculateCPURateDlg *)pDlg;
10     if (pItemDlg == NULL)
11     {
12         return;
13     }
14 
15     while(1)
16     {
17         double cpurate;
18         __int64 idle, kernel, user;
19         FILETIME preidleTime, idleTime;      //空闲时间
20         FILETIME prekernelTime, kernelTime;  //内核态时间
21         FILETIME preuserTime, userTime;      //用户态时间
22 
23         //计算CPU使用率,需要收集两份样本,中间用Sleep()函数间隔1s
24         GetSystemTimes(&preidleTime, &prekernelTime, &preuserTime);
25         Sleep(1000);
26         GetSystemTimes(&idleTime, &kernelTime, &userTime);
27 
28         idle = DiffFileTime(preidleTime, idleTime);
29         kernel = DiffFileTime(prekernelTime, kernelTime);
30         user = DiffFileTime(preuserTime, userTime);
31 
32         if (kernel + user == 0)
33             cpurate = 0.0;
34         else
35             cpurate = abs((kernel + user - idle) * 100 / (kernel + user));//(总的时间-空闲时间)/总的时间=占用cpu的时间就是使用率
36         
37         pItemDlg->m_RateResult2.Format(L"%.0lf%%", cpurate);
38         SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE); 
39     }
40 }

方式三:使用windows API(NtQuerySystemInformation)获取CPU利用率

 1 typedef struct _UINT64_DELTA
 2 {
 3     ULONG64 Value;
 4     ULONG64 Delta;
 5 } UINT64_DELTA, *PUINT64_DELTA;
 6 
 7 #define UpdateDelta(DltMgr, NewValue) 
 8 ((DltMgr)->Delta = (NewValue) - (DltMgr)->Value, 
 9 (DltMgr)->Value = (NewValue), (DltMgr)->Delta)
10 
11 void CThread::InitCalcuNt(void *pDlg)
12 {
13     CCalculateCPURateDlg *pItemDlg = (CCalculateCPURateDlg *)pDlg;
14     if (pItemDlg == NULL)
15     {
16         return;
17     }
18 
19     while(1)
20     {
21         double cpu_rate;
22         ULONG64 total_time = 0;
23         ULONG64 sys_time = 0;
24         static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION CpuInformation[1024];
25         static SYSTEM_INFO sys_info;
26 
27         static UINT64_DELTA cpu_kernel_delta;
28         static UINT64_DELTA cpu_user_delta;
29         static UINT64_DELTA cpu_idle_delta;
30         static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpu_totals;
31         memset(&cpu_totals, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
32 
33         GetSystemInfo(&sys_info);
34 
35         NtQuerySystemInformation(
36             SystemProcessorPerformanceInformation,
37             &CpuInformation,
38             sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * (ULONG)sys_info.dwNumberOfProcessors,
39             NULL
40             );
41 
42         for (int i = 0; i < (int)sys_info.dwNumberOfProcessors; i++)
43         {
44             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpu_info = CpuInformation[i];
45 
46             // KernelTime includes idle time.
47             LONGLONG dpc_time = cpu_info.Reserved1[0].QuadPart;
48             LONGLONG interrupt_time = cpu_info.Reserved1[i].QuadPart;
49             cpu_info.KernelTime.QuadPart -= cpu_info.IdleTime.QuadPart;
50             cpu_info.KernelTime.QuadPart += dpc_time + interrupt_time;
51 
52             cpu_totals.Reserved1[0].QuadPart += dpc_time;
53             cpu_totals.IdleTime.QuadPart += cpu_info.IdleTime.QuadPart;
54             cpu_totals.Reserved2 += cpu_info.Reserved2;
55             cpu_totals.Reserved1[1].QuadPart += cpu_info.Reserved1[1].QuadPart;
56             cpu_totals.KernelTime.QuadPart += cpu_info.KernelTime.QuadPart;
57             cpu_totals.UserTime.QuadPart += cpu_info.UserTime.QuadPart;
58         }
59 
60         UpdateDelta(&cpu_kernel_delta, cpu_totals.KernelTime.QuadPart);
61         UpdateDelta(&cpu_user_delta, cpu_totals.UserTime.QuadPart);
62         UpdateDelta(&cpu_idle_delta, cpu_totals.IdleTime.QuadPart);
63 
64         total_time = cpu_kernel_delta.Delta + cpu_user_delta.Delta + cpu_idle_delta.Delta;
65         sys_time = cpu_kernel_delta.Delta + cpu_user_delta.Delta;
66 
67         if (total_time)
68             cpu_rate = sys_time * 100.0 / total_time;
69         else
70             cpu_rate = 0.0;
71         pItemDlg->m_RateResult3.Format(L"%.0lf%%", cpu_rate);
72         Sleep(1000);
73 
74         SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE); 
75     }
76 }

4、stdafx.h 中添加

#pragma comment(lib,"pdh.lib")
#pragma comment(lib,"ntdll.lib")
#include <Pdh.h>
#include <PdhMsg.h>
#include <Windows.h> 
#include <Winternl.h>

错误:

1、在线程中调用UpdateData函数,在Debug模式下编译可以通过,但运行时会触发中断

获取电脑实时CPU使用率第3张

原因:MFC对象不支持多线程操作,不能供多个线程进程使用。子线程调用pDlg-> UpdateData(FALSE)时主线程(界面线程)会阻塞,更新必须由它完成,这样就形成死锁。更改界面的操作最好用主线程(界面线程),要想在子线程(工作线程)里执行界面的操作,可以通过向主线程发送消息来解决。

解决:

####Dlg.h 中添加

#define WM_UPDATEDATA  10000+1

afx_msg LRESULT OnUpdateData(WPARAM wParam, LPARAM lParam);

####Dlg.cpp 中添加

ON_MESSAGE(WM_UPDATEDATA, OnUpdateData) 

LRESULT CCalculateCPURateDlg::OnUpdateData(WPARAM wParam, LPARAM lParam) 
{ 
    UpdateData(wParam); 
    return 0; 
} 

Thread.cpp 中添加

SendMessage(pItemDlg->m_hWnd, WM_UPDATEDATA, FALSE, FALSE);

2、在某些环境中exe文件运行失败

解决:Release使用MT选项编译,Debug使用MTd选项编译(同时属性页中选择在静态库中使用MFC)

获取电脑实时CPU使用率第4张

参考博客:

https://www.cnblogs.com/einyboy/archive/2012/06/13/2548243.html

http://www.cnblogs.com/hbccdf/p/get_sys_cpu_usage_and_mem_usage.html

免责声明:文章转载自《获取电脑实时CPU使用率》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇FTP服务器高级配置Flask- celery (芹菜)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java:CAS(乐观锁)

本文讲解CAS机制,主要是因为最近准备面试题,发现这个问题在面试中出现的频率非常的高,因此把自己学习过程中的一些理解记录下来,希望能对大家也有帮助。 什么是悲观锁、乐观锁?在java语言里,总有一些名词看语义跟本不明白是啥玩意儿,也就总有部分面试官拿着这样的词来忽悠面试者,以此来找优越感,其实理解清楚了,这些词也就唬不住人了。 synchronize...

Windows I/O完成端口

内容: 1、基本概念2、WINDOWS完成端口的特点3、完成端口(Completion Ports )相关数据结构和创建4、完成端口线程的工作原理5、Windows完成端口的实例代码 WINDOWS完成端口编程 摘要:开发网络程序从来都不是一件容易的事情,尽管只需要遵守很少的一些规则:创建socket,发起连接,接受连接,发送和接收数据,等等。真正的困难在...

VS调试技巧

下面有从浅入深的6个问题,您可以尝试回答一下 一个如下的语句for (int i = 0; i < 10; i++){if (i == 5)j = 5;},什么都写在一行,你怎么在j=5前面插入断点 在一个1000次的循环体内部设置断点,你希望当循环进行到900次后中断,怎么才能做到呢? 你有一个表达式在上面循环的某一次发生了变化,你想知道是哪一次...

nginx配置及性能调优

https://www.toutiao.com/i6765746230141125132/?timestamp=1575450096&app=news_article&group_id=6765746230141125132&req_id=201912041701360100260760263C04643 2.4、配置默认主页loc...

linux系统性能分析

性能调优的第一步是性能分析,下面从性能分析着手进行一些介绍,尤其对Linux性能分析工具vmstat的用法和实践进行详细介绍。   1、性能分析的目的 1)找出系统性能瓶颈(包括硬件瓶颈和软件瓶颈); 2)提供性能优化的方案(升级硬件?改进系统系统结构?); 3)达到合理的硬件和软件配置; 4)使系统资源使用达到最大的平衡。(一般情况下系统良好运行的时候恰...

【Python之路】特别篇--多线程与多进程

并发 与 并行 的区别: 解释一:并发是在同一实体上的多个事件,并行是在不同实体上的多个事件; 解释二:并发是指两个或多个事件在同一时间间隔发生,而并行是指两个或者多个事件在同一时刻发生。 并发:就是同时做多件事情。 例如:终端用户程序利用并发功能,在输入数据的同时响应用户输入。服务器利用并发,在处理第一个请求的同时响应第二个请求。只要你希望程序同时做多件...