#include "ThreadCompareItemManager.h" #include "GlobalInfo.h" #include "SystemConfig.h" #include "CompareItemThread.h" #include "ThreadPool.h" #include "OneThread.h" /* 给对比项套一层壳,这个函数就是新的线程,在里面new出新的对比项实例,防止Qt报线程归属权错误 在函数中将对比项实例插入到线程管理器中 */ void ThreadCompareItemManager::thread_compareItem(CalculateThreadInfo_t threadInfo) { auto pThread = new CompareItemThread(threadInfo); if(pThread == nullptr) { SPDLOG_ERROR("ThreadCompareItemManager: 创建对比项线程失败"); return; } CompareItemManager.addCompareItemThread(pThread); /* 启动线程,就会一直阻塞在这里了 */ pThread->threadTask(); } ThreadCompareItemManager::ThreadCompareItemManager() { } ThreadCompareItemManager::~ThreadCompareItemManager() { } /* 线程函数 */ void ThreadCompareItemManager::thread_CompareItemManager() { m_logger = spdlog::get("CompareItemManager"); if(m_logger == nullptr) { fmt::print("ThreadCompareItemManager: CompareItemManager Logger not found.\n"); return; } /* 初始化webapi */ m_webAPIUrl = GInfo.webAPIUrl(); m_webAPIID = GInfo.webAPIID(); m_appType = GInfo.appType(); if(!m_fromWebAPI.initWebApi(m_webAPIUrl, m_webAPIID, m_appType)) { SPDLOG_LOGGER_ERROR(m_logger, "ThreadCompareItemManager: 初始化WebAPI失败"); return; } /* 创建一些变量 */ int threadSleepTime = 2; // 线程休眠时间,单位秒 QList listCreateItems; // 新创建的对比项列表 QList listUpdateItems; // 更新的对比项列表 QList listDeleteItems; // 删除的对比项列表 /* 获取基础配置,目前只获取一次 */ updateBaseSettings(); SPDLOG_LOGGER_INFO(m_logger, "开启对比项管理线程"); while(true) { std::this_thread::sleep_for(std::chrono::seconds(threadSleepTime)); if(threadSleepTime < 10) { /* 线程睡眠时间恢复为10秒 */ threadSleepTime = 10; } /* ------------------------------ 处理对比项信息 ------------------------------ */ /* 获取对比项信息 */ if(!m_fromWebAPI.getCompareItemInfo(m_listNewItems)) { SPDLOG_LOGGER_DEBUG(m_logger, "ThreadCompareItemManager: 获取对比项失败"); continue; } processCompareItemInfo(listCreateItems, listUpdateItems, listDeleteItems); SPDLOG_LOGGER_DEBUG(m_logger, "要退出的对比项个数: {}, 要更新的对比项个数: {}, 要创建的对比项个数: {}", listDeleteItems.size(), listUpdateItems.size(), listCreateItems.size()); /* 先删除已消失的对比项信息 */ processDeleteCompareItemThreads(listDeleteItems); /* 更新需要更新的线程 */ updateRunningThreads(listUpdateItems); /* 再创建新的对比项线程 */ createNewCompareItemThreads(listCreateItems); } SPDLOG_LOGGER_INFO(m_logger, "ThreadCompareItemManager: 线程结束"); } /* 添加对比项实例 */ void ThreadCompareItemManager::addCompareItemThread(CompareItemThread* pThread) { if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "添加对比项线程失败,线程指针为空"); return; } std::lock_guard lock(m_mutexCompareItemThreads); int compareItemID = pThread->getThreadInfo().compareItemInfo.nID; if(m_mapThreads.contains(compareItemID)) { SPDLOG_LOGGER_WARN(m_logger, "对比项线程已存在,ID: {}", compareItemID); return; // 对比项线程已存在 } m_mapThreads.insert(compareItemID, pThread); SPDLOG_LOGGER_INFO(m_logger, "添加对比项线程成功,ID: {}", compareItemID); } /* 更新基础设置信息,如数据库设置,噪音参数等 */ bool ThreadCompareItemManager::updateBaseSettings() { /* 更新基础数据 */ QMap baseSettings; if(!m_fromWebAPI.getSystemConfig(baseSettings)) { SPDLOG_LOGGER_ERROR(m_logger, "获取系统配置失败"); return false; } /* 将获取到的配置转换成结构体 */ SysConfig.parseConfigFromDatabase(baseSettings); /* 检测时段单独获取 */ QMap mapDetectConfig; if(!m_fromWebAPI.getDetectPeriodConfig(mapDetectConfig)) { SPDLOG_ERROR("获取对比项检测时段配置失败"); return false; } SysConfig.setDetectPeriodConfig(mapDetectConfig); return true; } /** * @brief 处理对比项信息,新获取的和已有的对比 * * @param createList 创建列表 * @param updateList 更新列表,根据对比项ID进行更新信息 * @param deleteList 删除列表 */ void ThreadCompareItemManager::processCompareItemInfo(QList& createList, QList& updateList, QList& deleteList) { createList.clear(); updateList.clear(); deleteList.clear(); QMap mapNowItems; /* 先从对比项线程中获取对比项信息 */ for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it) { BaseCalculateThread* pThread = it.value(); if(pThread == nullptr) { continue; } /* 获取对比项信息 */ CompareItemInfo_t itemInfo = pThread->getThreadInfo().compareItemInfo; mapNowItems.insert(itemInfo.nID, itemInfo); } /* 遍历新获取的对比项信息,找出需要新增的对比项和需要更新的对比项 */ for(const CompareItemInfo_t& item : m_listNewItems) { if(!mapNowItems.contains(item.nID)) { /* 新对比项,添加到创建列表 */ createList.append(item); } else { /* 已有对比项,检查是否需要更新 */ const CompareItemInfo_t& existingItem = mapNowItems.value(item.nID); /* 先对比基础信息 */ if(!existingItem.isEqualBase(item)) { /* 基础信息不同,需要更新 */ updateList.append(item); continue; } /* 在对比对比项通道信息 */ if(!existingItem.isEqualRoads(item)) { /* 通道信息不同,需要更新 */ updateList.append(item); continue; } } } /* 遍历当前对比项信息,找出需要删除的对比项 */ for(auto it : mapNowItems) { bool isFound = false; for(const CompareItemInfo_t& newItem : m_listNewItems) { if(it.nID == newItem.nID) { isFound = true; break; // 找到对应的对比项,不需要删除 } } if(!isFound) { /* 当前对比项不在新获取的对比项中,说明需要删除 */ deleteList.append(it.nID); } } } /** * @brief 处理需要删除的对比项线程 * 1、先处理已经停止的线程 * 2、再将这次列表中的对比项ID对应的线程设置为停止状态,待到下次循环再删除已经停止完成的线程 * * @param deleteList */ void ThreadCompareItemManager::processDeleteCompareItemThreads(const QList& deleteList) { /* 先处理已经停止运行的线程 */ for(auto it = m_mapThreads.begin(); it != m_mapThreads.end();) { BaseCalculateThread* pThread = it.value(); if(pThread == nullptr) { SPDLOG_LOGGER_WARN(m_logger, "对比项线程指针为空,即将删除该线程指针"); it = m_mapThreads.erase(it); continue; } if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped) { /* 线程已经停止,直接删除 */ SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已经停止,准备删除", pThread->getThreadInfo().compareItemInfo.strName.toStdString()); delete pThread; it = m_mapThreads.erase(it); continue; } ++it; } /* 停止本次需要停止的线程 */ for(auto it : m_mapThreads) { int compareItemID = it->getThreadInfo().compareItemInfo.nID; if(deleteList.contains(compareItemID)) { /* 设置线程停止标志 */ it->stopThread(); SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 设置为停止状态", it->getThreadInfo().compareItemInfo.strName.toStdString()); } } } /* 更新正在运行的线程信息 */ void ThreadCompareItemManager::updateRunningThreads(const QList& updateList) { if(updateList.isEmpty()) { return; } for(const CompareItemInfo_t& item : updateList) { auto it = m_mapThreads.find(item.nID); if(it == m_mapThreads.end()) { SPDLOG_LOGGER_WARN(m_logger, "对比项线程 {} 不存在,无法更新信息", item.strName.toStdString()); continue; } BaseCalculateThread* pThread = it.value(); if(pThread == nullptr) { continue; } CalculateThreadInfo_t threadInfo; threadInfo.compareItemInfo = item; pThread->updateThreadInfo(threadInfo); } } /* 创建新的线程 */ bool ThreadCompareItemManager::createNewCompareItemThreads(const QList& createList) { if(createList.isEmpty()) { SPDLOG_LOGGER_DEBUG(m_logger, "没有新的对比项需要创建"); return true; } for(auto& it : createList) { /* 创建新的对比项线程 */ CalculateThreadInfo_t threadInfo; threadInfo.compareItemInfo = it; threadInfo.threadType = EThreadType::Type_CompareItem; threadInfo.threadState = EThreadState::State_Inited; CPPTP.add_task(&ThreadCompareItemManager::thread_compareItem, threadInfo); /* 创建线程对象 */ // CompareItemThread* pThread = new CompareItemThread(threadInfo); // if(pThread == nullptr) // { // SPDLOG_LOGGER_ERROR(m_logger, "创建对比项线程 {} 失败", it.strName.toStdString()); // return false; // } /* 启动线程 */ // CPPTP.add_task(&CompareItemThread::threadTask, pThread); /* 添加到线程列表中 */ // m_mapThreads.insert(it.nID, pThread); } return true; }