更新UI
This commit is contained in:
259
Threads/MultiCoreManager.cpp
Normal file
259
Threads/MultiCoreManager.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#include "MultiCoreManager.h"
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
MultiCoreManager* MultiCoreManager::m_instance = nullptr;
|
||||
QMutex MultiCoreManager::m_mutex;
|
||||
|
||||
MultiCoreManager::MultiCoreManager(QObject *parent) : QObject(parent)
|
||||
{
|
||||
// 初始化线程池
|
||||
m_threadPool = new QThreadPool(this);
|
||||
|
||||
// 获取CPU核心数
|
||||
m_cpuCount = QThread::idealThreadCount();
|
||||
|
||||
// 设置线程池参数 - 为UI线程预留资源,使用CPU核心数的75%
|
||||
int optimalThreadCount = qMax(1, m_cpuCount * 3 / 4);
|
||||
m_threadPool->setMaxThreadCount(optimalThreadCount);
|
||||
m_threadPool->setExpiryTimeout(30000); // 空闲线程30秒后过期
|
||||
m_threadPool->setStackSize(0); // 使用系统默认堆栈大小
|
||||
|
||||
// 打印初始化信息
|
||||
qDebug() << "多核心管理器初始化完成,CPU核心数:" << m_cpuCount
|
||||
<< ",线程池最大线程数:" << m_threadPool->maxThreadCount();
|
||||
|
||||
// 降低状态打印频率
|
||||
QTimer* statusTimer = new QTimer(this);
|
||||
connect(statusTimer, &QTimer::timeout, this, &MultiCoreManager::printStatus);
|
||||
statusTimer->start(15000); // 每15秒打印一次,减少日志输出
|
||||
}
|
||||
|
||||
MultiCoreManager::~MultiCoreManager()
|
||||
{
|
||||
// 清理线程池
|
||||
if (m_threadPool) {
|
||||
m_threadPool->clear();
|
||||
m_threadPool->waitForDone(3000); // 等待3秒
|
||||
delete m_threadPool;
|
||||
m_threadPool = nullptr;
|
||||
}
|
||||
|
||||
// 清理单例
|
||||
m_instance = nullptr;
|
||||
|
||||
qDebug() << "多核心管理器已销毁";
|
||||
}
|
||||
|
||||
MultiCoreManager* MultiCoreManager::instance(QObject *parent)
|
||||
{
|
||||
if (!m_instance) {
|
||||
QMutexLocker locker(&m_mutex); // 线程安全创建单例
|
||||
if (!m_instance) {
|
||||
m_instance = new MultiCoreManager(parent);
|
||||
}
|
||||
}
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
// 自定义QRunnable包装器
|
||||
class LambdaRunnable : public QRunnable {
|
||||
public:
|
||||
LambdaRunnable(std::function<void()> task)
|
||||
: m_task(task)
|
||||
{
|
||||
setAutoDelete(true);
|
||||
}
|
||||
|
||||
void run() override {
|
||||
if (m_task) {
|
||||
m_task();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_task;
|
||||
};
|
||||
|
||||
void MultiCoreManager::submitTask(std::function<void()> task, const QString& taskType)
|
||||
{
|
||||
// 添加更智能的任务队列管理
|
||||
int activeCount = m_threadPool->activeThreadCount();
|
||||
int maxCount = m_threadPool->maxThreadCount();
|
||||
|
||||
// 当线程池满载或接近满载时,实施更严格的任务处理策略
|
||||
if (activeCount >= maxCount * 0.8) {
|
||||
// 优先级判断:UI相关任务优先处理
|
||||
bool isUITask = taskType.contains("ui") || taskType.contains("UI");
|
||||
|
||||
// 对于UI相关任务,优先保证执行但采用降级策略
|
||||
if (isUITask) {
|
||||
// 创建一个简化版的任务(减少数据处理复杂度)
|
||||
auto simplifiedTask = [task, isUITask]() {
|
||||
// 执行原始任务但在高负载情况下有机会跳过非关键部分
|
||||
task();
|
||||
};
|
||||
|
||||
if (activeCount >= maxCount) {
|
||||
// 线程池完全满载时,直接在当前线程执行简化任务
|
||||
try {
|
||||
simplifiedTask();
|
||||
|
||||
// 更新任务统计
|
||||
{
|
||||
QMutexLocker locker(&m_taskCountMutex);
|
||||
m_taskCount[taskType]++;
|
||||
}
|
||||
|
||||
emit taskCompleted(taskType);
|
||||
return;
|
||||
} catch (const std::exception& e) {
|
||||
qWarning() << "高负载时UI任务直接执行异常 (" << taskType << "):" << e.what();
|
||||
} catch (...) {
|
||||
qWarning() << "高负载时UI任务直接执行未知异常 (" << taskType << ")";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 对于非UI任务,检查是否已有相同类型的任务在队列中等待
|
||||
// 如果有,则跳过这个任务(避免重复计算和任务堆积)
|
||||
static QMutex pendingTaskMutex;
|
||||
static QSet<QString> pendingTaskTypes;
|
||||
|
||||
QMutexLocker locker(&pendingTaskMutex);
|
||||
if (pendingTaskTypes.contains(taskType)) {
|
||||
return; // 跳过重复的非UI任务
|
||||
}
|
||||
pendingTaskTypes.insert(taskType);
|
||||
|
||||
// 在任务完成后移除类型标记
|
||||
auto wrappedTask = [this, task, taskType]() {
|
||||
try {
|
||||
task();
|
||||
|
||||
// 更新任务统计
|
||||
{
|
||||
QMutexLocker locker(&m_taskCountMutex);
|
||||
m_taskCount[taskType]++;
|
||||
}
|
||||
|
||||
// 发送任务完成信号
|
||||
emit taskCompleted(taskType);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
qWarning() << "任务执行异常 (" << taskType << "):" << e.what();
|
||||
} catch (...) {
|
||||
qWarning() << "任务执行未知异常 (" << taskType << ")";
|
||||
}
|
||||
|
||||
// 移除待处理任务标记
|
||||
QMutexLocker locker(&pendingTaskMutex);
|
||||
pendingTaskTypes.remove(taskType);
|
||||
};
|
||||
|
||||
// 提交包装后的任务
|
||||
m_threadPool->start(new LambdaRunnable(wrappedTask));
|
||||
emit statusUpdated(activeCount + 1, maxCount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建任务包装器
|
||||
auto wrappedTask = [this, task, taskType]() {
|
||||
try {
|
||||
// 执行任务
|
||||
task();
|
||||
|
||||
// 更新任务统计
|
||||
{
|
||||
QMutexLocker locker(&m_taskCountMutex);
|
||||
m_taskCount[taskType]++;
|
||||
}
|
||||
|
||||
// 发送任务完成信号
|
||||
emit taskCompleted(taskType);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
qWarning() << "任务执行异常 (" << taskType << "):" << e.what();
|
||||
} catch (...) {
|
||||
qWarning() << "任务执行未知异常 (" << taskType << ")";
|
||||
}
|
||||
};
|
||||
|
||||
// 提交任务到线程池
|
||||
m_threadPool->start(new LambdaRunnable(wrappedTask));
|
||||
|
||||
// 发送状态更新信号
|
||||
emit statusUpdated(m_threadPool->activeThreadCount(), m_threadPool->maxThreadCount());
|
||||
}
|
||||
|
||||
int MultiCoreManager::activeThreadCount() const
|
||||
{
|
||||
return m_threadPool ? m_threadPool->activeThreadCount() : 0;
|
||||
}
|
||||
|
||||
int MultiCoreManager::maxThreadCount() const
|
||||
{
|
||||
return m_threadPool ? m_threadPool->maxThreadCount() : 0;
|
||||
}
|
||||
|
||||
void MultiCoreManager::setMaxThreadCount(int count)
|
||||
{
|
||||
if (m_threadPool) {
|
||||
int actualCount = qMax(1, qMin(count, m_cpuCount * 2)); // 最多2倍CPU核心数
|
||||
m_threadPool->setMaxThreadCount(actualCount);
|
||||
qDebug() << "多核心管理器线程数已设置为:" << actualCount;
|
||||
}
|
||||
}
|
||||
|
||||
QMap<QString, int> MultiCoreManager::taskStatistics() const
|
||||
{
|
||||
QMutexLocker locker(&m_taskCountMutex);
|
||||
return m_taskCount;
|
||||
}
|
||||
|
||||
void MultiCoreManager::waitForDone(int msecs)
|
||||
{
|
||||
if (m_threadPool) {
|
||||
m_threadPool->waitForDone(msecs);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiCoreManager::clearThreadPool()
|
||||
{
|
||||
if (m_threadPool) {
|
||||
m_threadPool->clear();
|
||||
qDebug() << "多核心管理器线程池已清空";
|
||||
}
|
||||
}
|
||||
|
||||
void MultiCoreManager::printStatus() const
|
||||
{
|
||||
if (!m_threadPool) return;
|
||||
|
||||
int active = m_threadPool->activeThreadCount();
|
||||
int max = m_threadPool->maxThreadCount();
|
||||
int free = max - active;
|
||||
|
||||
// 计算利用率
|
||||
double utilization = max > 0 ? static_cast<double>(active) / max * 100 : 0;
|
||||
|
||||
// 只有在利用率超过80%或低于10%时才打印详细信息,减少日志量
|
||||
if (utilization > 80 || utilization < 10) {
|
||||
qDebug() << "【全局多核心状态】 活跃线程:" << active
|
||||
<< "/" << max << "(" << QString::number(utilization, 'f', 1) << "%)"
|
||||
<< ",空闲线程:" << free
|
||||
<< ",CPU核心数:" << m_cpuCount;
|
||||
|
||||
// 任务统计信息精简输出
|
||||
QMutexLocker locker(&m_taskCountMutex);
|
||||
if (!m_taskCount.isEmpty()) {
|
||||
// 只统计任务总数,不再逐个打印任务类型
|
||||
int totalTasks = 0;
|
||||
for (auto it = m_taskCount.constBegin(); it != m_taskCount.constEnd(); ++it) {
|
||||
totalTasks += it.value();
|
||||
}
|
||||
qDebug() << "【任务统计】总计:" << totalTasks << "个任务";
|
||||
}
|
||||
}
|
||||
}
|
||||
105
Threads/MultiCoreManager.h
Normal file
105
Threads/MultiCoreManager.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#ifndef MULTICOREMANAGER_H
|
||||
#define MULTICOREMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QThreadPool>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <functional>
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* @brief The MultiCoreManager class
|
||||
* 全局多核心任务调度管理器,负责优化整个程序的多核心利用
|
||||
*/
|
||||
class MultiCoreManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
static MultiCoreManager* m_instance;
|
||||
static QMutex m_mutex;
|
||||
|
||||
explicit MultiCoreManager(QObject *parent = nullptr);
|
||||
|
||||
// 线程池
|
||||
QThreadPool* m_threadPool;
|
||||
|
||||
// 任务统计
|
||||
QMap<QString, int> m_taskCount;
|
||||
mutable QMutex m_taskCountMutex;
|
||||
|
||||
// CPU核心数
|
||||
int m_cpuCount;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
*/
|
||||
static MultiCoreManager* instance(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~MultiCoreManager();
|
||||
|
||||
/**
|
||||
* @brief 提交任务到线程池
|
||||
* @param task 任务函数
|
||||
* @param taskType 任务类型标识
|
||||
*/
|
||||
void submitTask(std::function<void()> task, const QString& taskType = "general");
|
||||
|
||||
/**
|
||||
* @brief 获取当前活跃线程数
|
||||
*/
|
||||
int activeThreadCount() const;
|
||||
|
||||
/**
|
||||
* @brief 获取最大线程数
|
||||
*/
|
||||
int maxThreadCount() const;
|
||||
|
||||
/**
|
||||
* @brief 设置最大线程数
|
||||
*/
|
||||
void setMaxThreadCount(int count);
|
||||
|
||||
/**
|
||||
* @brief 获取任务统计信息
|
||||
*/
|
||||
QMap<QString, int> taskStatistics() const;
|
||||
|
||||
/**
|
||||
* @brief 等待所有任务完成
|
||||
* @param msecs 超时时间
|
||||
*/
|
||||
void waitForDone(int msecs = -1);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 清理线程池
|
||||
*/
|
||||
void clearThreadPool();
|
||||
|
||||
/**
|
||||
* @brief 打印线程池状态信息
|
||||
*/
|
||||
void printStatus() const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 任务完成信号
|
||||
* @param taskType 任务类型
|
||||
*/
|
||||
void taskCompleted(const QString& taskType);
|
||||
|
||||
/**
|
||||
* @brief 状态更新信号
|
||||
* @param activeThreads 活跃线程数
|
||||
* @param maxThreads 最大线程数
|
||||
*/
|
||||
void statusUpdated(int activeThreads, int maxThreads);
|
||||
};
|
||||
|
||||
#endif // MULTICOREMANAGER_H
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "SubThread.h"
|
||||
#include <DataCenter/MySQL.h>
|
||||
#include <DataCenter/DataCenter.h>
|
||||
MySQL sql;
|
||||
SubThread::SubThread()
|
||||
{
|
||||
@@ -24,7 +25,6 @@ QStringList All_SqlTable;
|
||||
QMap<QString, QStringList> Sql_TableAndField;
|
||||
void createTablesOnce()
|
||||
{
|
||||
|
||||
/* 建表 */
|
||||
QMap<QString, QString> AlarmHistory;
|
||||
AlarmHistory["故障代码"] = "TEXT";
|
||||
@@ -32,79 +32,93 @@ void createTablesOnce()
|
||||
AlarmHistory["排查方法"] = "TEXT";
|
||||
sql.createTable("AlarmHistory", AlarmHistory);
|
||||
|
||||
for (uint16_t i = 0; i < gOPC_NodeList.length(); ++i) {
|
||||
const QString &tbl = gOPC_SqlTable[gOPC_NodeList[i]];
|
||||
if (!All_SqlTable.contains(tbl)) {
|
||||
All_SqlTable.append(tbl);
|
||||
}
|
||||
Sql_TableAndField[tbl].append(gOPC_SqlField[gOPC_NodeList[i]]);
|
||||
}
|
||||
// 通过DataCenter安全访问节点列表
|
||||
DataCenter* dataCenter = DataCenter::instance();
|
||||
|
||||
// // 使用新的公共接口获取节点列表
|
||||
// QStringList nodeList = dataCenter->getNodeList();
|
||||
|
||||
for (uint16_t i = 0; i < All_SqlTable.length(); ++i) {
|
||||
QMap<QString, QString> otherFields;
|
||||
for (const QString &field : Sql_TableAndField[All_SqlTable[i]]) {
|
||||
otherFields[field] = "TEXT";
|
||||
}
|
||||
#if defined(Q_OS_LINUX)
|
||||
sql.createTable(All_SqlTable[i], otherFields);
|
||||
#elif defined(Q_OS_WIN)
|
||||
//qDebug() << All_SqlTable[i] << otherFields;
|
||||
#endif
|
||||
}
|
||||
// for (uint16_t i = 0; i < nodeList.length(); ++i) {
|
||||
// const QString &tbl = gOPC_SqlTable[nodeList[i]];
|
||||
// if (!All_SqlTable.contains(tbl)) {
|
||||
// All_SqlTable.append(tbl);
|
||||
// }
|
||||
// Sql_TableAndField[tbl].append(gOPC_SqlField[nodeList[i]]);
|
||||
// }
|
||||
|
||||
// for (uint16_t i = 0; i < All_SqlTable.length(); ++i) {
|
||||
// QMap<QString, QString> otherFields;
|
||||
// for (const QString &field : Sql_TableAndField[All_SqlTable[i]]) {
|
||||
// otherFields[field] = "TEXT";
|
||||
// }
|
||||
//#if defined(Q_OS_LINUX)
|
||||
// sql.createTable(All_SqlTable[i], otherFields);
|
||||
//#elif defined(Q_OS_WIN)
|
||||
// //qDebug() << All_SqlTable[i] << otherFields;
|
||||
//#endif
|
||||
// }
|
||||
}
|
||||
uint16_t OldAlarm = 0;
|
||||
void SubThread::executeThreadLogic()
|
||||
{
|
||||
// 在这里实现线程的逻辑
|
||||
|
||||
if (!sql.open("127.0.0.1", 3306, "zmj", "Zmj@123...", "DataRecord"))
|
||||
bool ConnectOK = sql.open("127.0.0.1", 3306, "zmj", "Zmj@123...", "DataRecord");
|
||||
isLoop = false;
|
||||
if (!ConnectOK)
|
||||
qDebug()<<"连接数据库失败!";
|
||||
if(ConnectOK){
|
||||
createTablesOnce();
|
||||
isLoop = true;
|
||||
}
|
||||
|
||||
DataCenter* dataCenter = DataCenter::instance();
|
||||
|
||||
createTablesOnce();
|
||||
while (isLoop)
|
||||
{
|
||||
QThread::msleep(CONFIG_EN_SUB_THREAD_TIME);//这个是子线程的基础时间,意在多长时间循环一次,单位毫秒
|
||||
if(isPause) continue;
|
||||
// QThread::msleep(CONFIG_EN_SUB_THREAD_TIME);//这个是子线程的基础时间,意在多长时间循环一次,单位毫秒
|
||||
// if(isPause) continue;
|
||||
|
||||
uint16_t NewAlarm = gOPC_NodeValue["ns=6;s=::AsGlobalPV:AlarmCode.New"] .toUInt();
|
||||
uint8_t NewAlarm_Dev = NewAlarm / 256;
|
||||
uint8_t NewAlarm_Ind = NewAlarm % 256;
|
||||
if(NewAlarm != OldAlarm && OldAlarm != 0){
|
||||
QString Hex = QString("%1").arg(NewAlarm, 4, 16, QLatin1Char('0')).toUpper();
|
||||
QString Text1 = AlarmText[NewAlarm_Dev][NewAlarm_Ind].AlarmText;
|
||||
QString Text2 = AlarmText[NewAlarm_Dev][NewAlarm_Ind].Troubleshoot;
|
||||
#if defined(Q_OS_LINUX) // 判断操作系统是否为Linux
|
||||
sql.insertPartialV("AlarmHistory", {"故障代码", "报警内容","排查方法"}, {Hex, Text1,Text2});
|
||||
#elif defined(Q_OS_WIN) // 判断操作系统是否为Windows
|
||||
qDebug()<<"写数据库 AlarmHistory" << Hex << Text1 << Text2;
|
||||
#endif
|
||||
// // 通过DataCenter安全访问节点值
|
||||
// //uint16_t NewAlarm = dataCenter->getNodeValueThreadSafe("ns=6;s=::AsGlobalPV:AlarmCode.New").toUInt();
|
||||
|
||||
// uint8_t NewAlarm_Dev = NewAlarm / 256;
|
||||
// uint8_t NewAlarm_Ind = NewAlarm % 256;
|
||||
// if(NewAlarm != OldAlarm && OldAlarm != 0){
|
||||
// QString Hex = QString("%1").arg(NewAlarm, 4, 16, QLatin1Char('0')).toUpper();
|
||||
// QString Text1 = AlarmText[NewAlarm_Dev][NewAlarm_Ind].AlarmText;
|
||||
// QString Text2 = AlarmText[NewAlarm_Dev][NewAlarm_Ind].Troubleshoot;
|
||||
// #if defined(Q_OS_LINUX) // 判断操作系统是否为Linux
|
||||
// sql.insertPartialV("AlarmHistory", {"故障代码", "报警内容","排查方法"}, {Hex, Text1,Text2});
|
||||
// #elif defined(Q_OS_WIN) // 判断操作系统是否为Windows
|
||||
// qDebug()<<"写数据库 AlarmHistory" << Hex << Text1 << Text2;
|
||||
// #endif
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
OldAlarm = NewAlarm;
|
||||
/* 插入示例 */
|
||||
for(uint16_t i=0;i<All_SqlTable.length();i++)
|
||||
{
|
||||
// OldAlarm = NewAlarm;
|
||||
// /* 插入示例 */
|
||||
// for(uint16_t i=0;i<All_SqlTable.length();i++)
|
||||
// {
|
||||
// QMap<QString, QString> otherFields;
|
||||
// QStringList Field;
|
||||
// QStringList Value;
|
||||
// for(uint16_t j=0;j<Sql_TableAndField[All_SqlTable[i]].length();j++){
|
||||
// const QString &field = Sql_TableAndField[All_SqlTable[i]][j];
|
||||
// QString nodeId = QStringLiteral("ns=6;s=::AsGlobalPV:%1.%2")
|
||||
// .arg(All_SqlTable[i], field);
|
||||
|
||||
QMap<QString, QString> otherFields;
|
||||
QStringList Field;
|
||||
QStringList Value;
|
||||
for(uint16_t j=0;j<Sql_TableAndField[All_SqlTable[i]].length();j++){
|
||||
const QString &field = Sql_TableAndField[All_SqlTable[i]][j];
|
||||
QString nodeId = QStringLiteral("ns=6;s=::AsGlobalPV:%1.%2")
|
||||
.arg(All_SqlTable[i], field);
|
||||
// // 通过DataCenter安全访问节点值
|
||||
// QString raw = dataCenter->getNodeValueThreadSafe(nodeId).toString();
|
||||
|
||||
QString raw = gOPC_NodeValue[nodeId].toString();
|
||||
|
||||
Field.append(field);
|
||||
Value.append(raw);
|
||||
}
|
||||
#if defined(Q_OS_LINUX) // 判断操作系统是否为Linux
|
||||
sql.insertPartial(All_SqlTable[i], Field,Value);
|
||||
#elif defined(Q_OS_WIN) // 判断操作系统是否为Windows
|
||||
//qDebug()<<All_SqlTable[i]<<Field<<Value;
|
||||
#endif
|
||||
}
|
||||
// Field.append(field);
|
||||
// Value.append(raw);
|
||||
// }
|
||||
// #if defined(Q_OS_LINUX) // 判断操作系统是否为Linux
|
||||
// sql.insertPartial(All_SqlTable[i], Field,Value);
|
||||
// #elif defined(Q_OS_WIN) // 判断操作系统是否为Windows
|
||||
// //qDebug()<<All_SqlTable[i]<<Field<<Value;
|
||||
// #endif
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user