首先了解一下CPU使用率的计算方式,无论是单个进程cpu占用率还是系统整个cpu使用率,都是一样的计算公式:
- cpu使用率 = 运行时间 / 间隔时间
- 运行时间 = 内核时间 + 用户时间 - 空闲时间
- 间隔时间 = 内核时间 + 用户时间
根据上述公式的原理,在计算CPU使用率时需要阻塞/等待线程若干时间,一般这个时间为500ms/1000ms。由于需要阻塞线程,所以计算CPU使用率的函数是绝对不能写在主线程里的,因此另开一个线程用以计算该公式,代码如下:
worker.h(开启从线程计算CPU占用)
#pragma once
#include "windows.h"
#include <QObject>
#include <QThread>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject* parent = nullptr) { };
protected:
//时间转换
__int64 Filetime2Int64(const FILETIME* ftime)
{
LARGE_INTEGER li;
li.LowPart = ftime->dwLowDateTime;
li.HighPart = ftime->dwHighDateTime;
return li.QuadPart;
}
//两个时间相减运算
__int64 CompareFileTime(FILETIME preTime, FILETIME nowTime)
{
return this->Filetime2Int64(&nowTime) - this->Filetime2Int64(&preTime);
}
signals:
void resultReady(const int dosage); // 向外界发送结果
public slots:
void calCpuUsage()// 耗时操作
{
HANDLE hEvent;
bool res;
static FILETIME preIdleTime;
static FILETIME preKernelTime;
static FILETIME preUserTime;
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
preIdleTime = idleTime;
preKernelTime = kernelTime;
preUserTime = userTime;
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
WaitForSingleObject(hEvent, 500); //等待500毫秒
res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
int idle = CompareFileTime(preIdleTime, idleTime);
int kernel = CompareFileTime(preKernelTime, kernelTime);
int user = CompareFileTime(preUserTime, userTime);
auto nCpuRate = (int)ceil(100.0 * (kernel + user - idle) / (kernel + user));
emit resultReady(nCpuRate);
}
};
Controller.h
#pragma once
#include <QObject>
#include <QThread>
#include "worker.h"
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject* parent = nullptr);
~Controller();
int getCpuUsage();
signals:
void startRunning(); // 用于触发新线程中的耗时操作函数
public slots:
void on_receivResult(const int dosage); // 接收新线程中的结果
private:
QThread m_workThread;
Worker* m_worker;
int cpuDosage = 0;
};
Controller.cpp
#include "Controller.h"
#include <QThread>
#include <QDebug>
Controller::Controller(QObject* parent) : QObject(parent)
{
m_worker = new Worker();
m_worker->moveToThread(&m_workThread);
connect(this, &Controller::startRunning, m_worker, &Worker::calCpuUsage);
connect(&m_workThread, &QThread::finished, m_worker, &QObject::deleteLater);
connect(m_worker, &Worker::resultReady, this, &Controller::on_receivResult);
}
Controller::~Controller()
{
m_workThread.quit();
m_workThread.wait();
}
int Controller::getCpuUsage()
{
m_workThread.start();
emit startRunning();
return cpuDosage;
}
void Controller::on_receivResult(const int dosage)
{
cpuDosage = dosage;
}
使用方法:实例化Controller,调用getCpuUsage()即可。