ThreadCompareItemManager.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. #include "ThreadCompareItemManager.h"
  2. #include "GlobalInfo.h"
  3. #include "SystemConfig.h"
  4. #include "CompareItemThread.h"
  5. #include "ThreadPool.h"
  6. #include "OneThread.h"
  7. /* 给对比项套一层壳,这个函数就是新的线程,在里面new出新的对比项实例,防止Qt报线程归属权错误
  8. 在函数中将对比项实例插入到线程管理器中 */
  9. void ThreadCompareItemManager::thread_compareItem(CalculateThreadInfo_t threadInfo)
  10. {
  11. auto pThread = new CompareItemThread(threadInfo);
  12. if(pThread == nullptr)
  13. {
  14. SPDLOG_ERROR("ThreadCompareItemManager: 创建对比项线程失败");
  15. return;
  16. }
  17. CompareItemManager.addCompareItemThread(pThread);
  18. /* 启动线程,就会一直阻塞在这里了 */
  19. pThread->threadTask();
  20. }
  21. ThreadCompareItemManager::ThreadCompareItemManager()
  22. {
  23. }
  24. ThreadCompareItemManager::~ThreadCompareItemManager()
  25. {
  26. }
  27. /* 线程函数 */
  28. void ThreadCompareItemManager::thread_CompareItemManager()
  29. {
  30. m_logger = spdlog::get("CompareItemManager");
  31. if(m_logger == nullptr)
  32. {
  33. fmt::print("ThreadCompareItemManager: CompareItemManager Logger not found.\n");
  34. return;
  35. }
  36. /* 初始化webapi */
  37. m_webAPIUrl = GInfo.webAPIUrl();
  38. m_webAPIID = GInfo.webAPIID();
  39. m_appType = GInfo.appType();
  40. if(!m_fromWebAPI.initWebApi(m_webAPIUrl, m_webAPIID, m_appType))
  41. {
  42. SPDLOG_LOGGER_ERROR(m_logger, "ThreadCompareItemManager: 初始化WebAPI失败");
  43. return;
  44. }
  45. /* 创建一些变量 */
  46. int threadSleepTime = 2; // 线程休眠时间,单位秒
  47. QList<CompareItemInfo_t> listCreateItems; // 新创建的对比项列表
  48. QList<CompareItemInfo_t> listUpdateItems; // 更新的对比项列表
  49. QList<int> listDeleteItems; // 删除的对比项列表
  50. /* 获取基础配置,目前只获取一次 */
  51. updateBaseSettings();
  52. SPDLOG_LOGGER_INFO(m_logger, "开启对比项管理线程");
  53. while(true)
  54. {
  55. std::this_thread::sleep_for(std::chrono::seconds(threadSleepTime));
  56. if(threadSleepTime < 10)
  57. {
  58. /* 线程睡眠时间恢复为10秒 */
  59. threadSleepTime = 10;
  60. }
  61. /* ------------------------------ 处理对比项信息 ------------------------------ */
  62. /* 获取对比项信息 */
  63. if(!m_fromWebAPI.getCompareItemInfo(m_listNewItems))
  64. {
  65. SPDLOG_LOGGER_DEBUG(m_logger, "ThreadCompareItemManager: 获取对比项失败");
  66. continue;
  67. }
  68. processCompareItemInfo(listCreateItems, listUpdateItems, listDeleteItems);
  69. SPDLOG_LOGGER_DEBUG(m_logger, "要退出的对比项个数: {}, 要更新的对比项个数: {}, 要创建的对比项个数: {}",
  70. listDeleteItems.size(), listUpdateItems.size(), listCreateItems.size());
  71. /* 先删除已消失的对比项信息 */
  72. processDeleteCompareItemThreads(listDeleteItems);
  73. /* 更新需要更新的线程 */
  74. updateRunningThreads(listUpdateItems);
  75. /* 再创建新的对比项线程 */
  76. createNewCompareItemThreads(listCreateItems);
  77. }
  78. SPDLOG_LOGGER_INFO(m_logger, "ThreadCompareItemManager: 线程结束");
  79. }
  80. /* 添加对比项实例 */
  81. void ThreadCompareItemManager::addCompareItemThread(CompareItemThread* pThread)
  82. {
  83. if(pThread == nullptr)
  84. {
  85. SPDLOG_LOGGER_ERROR(m_logger, "添加对比项线程失败,线程指针为空");
  86. return;
  87. }
  88. std::lock_guard<std::mutex> lock(m_mutexCompareItemThreads);
  89. int compareItemID = pThread->getThreadInfo().compareItemInfo.nID;
  90. if(m_mapThreads.contains(compareItemID))
  91. {
  92. SPDLOG_LOGGER_WARN(m_logger, "对比项线程已存在,ID: {}", compareItemID);
  93. return; // 对比项线程已存在
  94. }
  95. m_mapThreads.insert(compareItemID, pThread);
  96. SPDLOG_LOGGER_INFO(m_logger, "添加对比项线程成功,ID: {}", compareItemID);
  97. }
  98. /* 更新基础设置信息,如数据库设置,噪音参数等 */
  99. bool ThreadCompareItemManager::updateBaseSettings()
  100. {
  101. /* 更新基础数据 */
  102. QMap<std::string, std::string> baseSettings;
  103. if(!m_fromWebAPI.getSystemConfig(baseSettings))
  104. {
  105. SPDLOG_LOGGER_ERROR(m_logger, "获取系统配置失败");
  106. return false;
  107. }
  108. /* 将获取到的配置转换成结构体 */
  109. for(auto it = baseSettings.begin(); it != baseSettings.end(); ++it)
  110. {
  111. if(Config_Base == it.key())
  112. {
  113. if(!SysConfig.getBaseConfigFromJson(it.value()))
  114. {
  115. SPDLOG_ERROR("获取基础配置失败");
  116. }
  117. }
  118. else if(Config_CompareAI == it.key())
  119. {
  120. if(!SysConfig.getAICompareConfigFromJson(it.value()))
  121. {
  122. SPDLOG_ERROR("获取AI对比配置失败");
  123. }
  124. }
  125. else if(Config_NoiseBase == it.key())
  126. {
  127. if(!SysConfig.getNoiseDetectBaseConfigFromJson(it.value()))
  128. {
  129. SPDLOG_ERROR("获取噪音检测基础配置失败");
  130. }
  131. }
  132. else if(Config_NoiseParam == it.key())
  133. {
  134. if(!SysConfig.getNoiseDetectParamFromJson(it.value()))
  135. {
  136. SPDLOG_ERROR("获取噪音检测参数失败");
  137. }
  138. }
  139. else if(Config_Database == it.key())
  140. {
  141. if(!SysConfig.getDatabaseConfigFromJson(it.value()))
  142. {
  143. SPDLOG_ERROR("获取数据库设置失败");
  144. }
  145. }
  146. else
  147. {
  148. SPDLOG_DEBUG("未知的系统配置项: {}", it.key());
  149. }
  150. }
  151. /* 检测时段单独获取 */
  152. QMap<int, DetectPeriodConfig_t> mapDetectConfig;
  153. if(!m_fromWebAPI.getDetectPeriodConfig(mapDetectConfig))
  154. {
  155. SPDLOG_ERROR("获取对比项检测时段配置失败");
  156. return false;
  157. }
  158. SysConfig.setDetectPeriodConfig(mapDetectConfig);
  159. return true;
  160. }
  161. /**
  162. * @brief 处理对比项信息,新获取的和已有的对比
  163. *
  164. * @param createList 创建列表
  165. * @param updateList 更新列表,根据对比项ID进行更新信息
  166. * @param deleteList 删除列表
  167. */
  168. void ThreadCompareItemManager::processCompareItemInfo(QList<CompareItemInfo_t>& createList, QList<CompareItemInfo_t>& updateList, QList<int>& deleteList)
  169. {
  170. createList.clear();
  171. updateList.clear();
  172. deleteList.clear();
  173. QMap<int, CompareItemInfo_t> mapNowItems;
  174. /* 先从对比项线程中获取对比项信息 */
  175. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it)
  176. {
  177. BaseCalculateThread* pThread = it.value();
  178. if(pThread == nullptr)
  179. {
  180. continue;
  181. }
  182. /* 获取对比项信息 */
  183. CompareItemInfo_t itemInfo = pThread->getThreadInfo().compareItemInfo;
  184. mapNowItems.insert(itemInfo.nID, itemInfo);
  185. }
  186. /* 遍历新获取的对比项信息,找出需要新增的对比项和需要更新的对比项 */
  187. for(const CompareItemInfo_t& item : m_listNewItems)
  188. {
  189. if(!mapNowItems.contains(item.nID))
  190. {
  191. /* 新对比项,添加到创建列表 */
  192. createList.append(item);
  193. } else
  194. {
  195. /* 已有对比项,检查是否需要更新 */
  196. const CompareItemInfo_t& existingItem = mapNowItems.value(item.nID);
  197. /* 先对比基础信息 */
  198. if(!existingItem.isEqualBase(item))
  199. {
  200. /* 基础信息不同,需要更新 */
  201. updateList.append(item);
  202. continue;
  203. }
  204. /* 在对比对比项通道信息 */
  205. if(!existingItem.isEqualRoads(item))
  206. {
  207. /* 通道信息不同,需要更新 */
  208. updateList.append(item);
  209. continue;
  210. }
  211. }
  212. }
  213. /* 遍历当前对比项信息,找出需要删除的对比项 */
  214. for(auto it : mapNowItems)
  215. {
  216. bool isFound = false;
  217. for(const CompareItemInfo_t& newItem : m_listNewItems)
  218. {
  219. if(it.nID == newItem.nID)
  220. {
  221. isFound = true;
  222. break; // 找到对应的对比项,不需要删除
  223. }
  224. }
  225. if(!isFound)
  226. {
  227. /* 当前对比项不在新获取的对比项中,说明需要删除 */
  228. deleteList.append(it.nID);
  229. }
  230. }
  231. }
  232. /**
  233. * @brief 处理需要删除的对比项线程
  234. * 1、先处理已经停止的线程
  235. * 2、再将这次列表中的对比项ID对应的线程设置为停止状态,待到下次循环再删除已经停止完成的线程
  236. *
  237. * @param deleteList
  238. */
  239. void ThreadCompareItemManager::processDeleteCompareItemThreads(const QList<int>& deleteList)
  240. {
  241. /* 先处理已经停止运行的线程 */
  242. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end();)
  243. {
  244. BaseCalculateThread* pThread = it.value();
  245. if(pThread == nullptr)
  246. {
  247. SPDLOG_LOGGER_WARN(m_logger, "对比项线程指针为空,即将删除该线程指针");
  248. it = m_mapThreads.erase(it);
  249. continue;
  250. }
  251. if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped)
  252. {
  253. /* 线程已经停止,直接删除 */
  254. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已经停止,准备删除", pThread->getThreadInfo().compareItemInfo.strName.toStdString());
  255. delete pThread;
  256. it = m_mapThreads.erase(it);
  257. continue;
  258. }
  259. ++it;
  260. }
  261. /* 停止本次需要停止的线程 */
  262. for(auto it : m_mapThreads)
  263. {
  264. int compareItemID = it->getThreadInfo().compareItemInfo.nID;
  265. if(deleteList.contains(compareItemID))
  266. {
  267. /* 设置线程停止标志 */
  268. it->stopThread();
  269. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 设置为停止状态", it->getThreadInfo().compareItemInfo.strName.toStdString());
  270. }
  271. }
  272. }
  273. /* 更新正在运行的线程信息 */
  274. void ThreadCompareItemManager::updateRunningThreads(const QList<CompareItemInfo_t>& updateList)
  275. {
  276. if(updateList.isEmpty())
  277. {
  278. return;
  279. }
  280. for(const CompareItemInfo_t& item : updateList)
  281. {
  282. auto it = m_mapThreads.find(item.nID);
  283. if(it == m_mapThreads.end())
  284. {
  285. SPDLOG_LOGGER_WARN(m_logger, "对比项线程 {} 不存在,无法更新信息", item.strName.toStdString());
  286. continue;
  287. }
  288. BaseCalculateThread* pThread = it.value();
  289. if(pThread == nullptr)
  290. {
  291. continue;
  292. }
  293. CalculateThreadInfo_t threadInfo;
  294. threadInfo.compareItemInfo = item;
  295. pThread->updateThreadInfo(threadInfo);
  296. }
  297. }
  298. /* 创建新的线程 */
  299. bool ThreadCompareItemManager::createNewCompareItemThreads(const QList<CompareItemInfo_t>& createList)
  300. {
  301. if(createList.isEmpty())
  302. {
  303. SPDLOG_LOGGER_DEBUG(m_logger, "没有新的对比项需要创建");
  304. return true;
  305. }
  306. for(auto& it : createList)
  307. {
  308. /* 创建新的对比项线程 */
  309. CalculateThreadInfo_t threadInfo;
  310. threadInfo.compareItemInfo = it;
  311. threadInfo.threadType = EThreadType::Type_CompareItem;
  312. threadInfo.threadState = EThreadState::State_Inited;
  313. CPPTP.add_task(&ThreadCompareItemManager::thread_compareItem, threadInfo);
  314. /* 创建线程对象 */
  315. // CompareItemThread* pThread = new CompareItemThread(threadInfo);
  316. // if(pThread == nullptr)
  317. // {
  318. // SPDLOG_LOGGER_ERROR(m_logger, "创建对比项线程 {} 失败", it.strName.toStdString());
  319. // return false;
  320. // }
  321. /* 启动线程 */
  322. // CPPTP.add_task(&CompareItemThread::threadTask, pThread);
  323. /* 添加到线程列表中 */
  324. // m_mapThreads.insert(it.nID, pThread);
  325. }
  326. return true;
  327. }