threadcontroller.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "threadcontroller.h"
  2. #include <QDebug>
  3. #if defined(Q_OS_WIN32)
  4. #include <windows.h>
  5. #include <tlhelp32.h>
  6. #endif
  7. #include <QPointer>
  8. /* 获取线程数 */
  9. int ThreadUtility::GetThreadCount(int processID)
  10. {
  11. #if defined(Q_OS_WIN32)
  12. PROCESSENTRY32 pe32;
  13. pe32.dwSize = sizeof(pe32);
  14. HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  15. if (hProcessSnap == INVALID_HANDLE_VALUE)
  16. {
  17. qDebug()<<"CreateToolhelp32Snapshot 调用失败";
  18. return -1;
  19. }
  20. BOOL bMore = ::Process32First(hProcessSnap, &pe32);
  21. //printf("%-30s %-20s %-20s %-15s\n","szExeFile","th32ProcessID","th32ParentProcessID","cntThreads");
  22. while(bMore)
  23. {
  24. //printf("%-30s ",pe32.szExeFile);
  25. //printf("%-20d ",pe32.th32ProcessID);
  26. //printf("%-20d",pe32.th32ParentProcessID);
  27. ////显示进程的线程数
  28. //printf("%-15d\n",pe32.cntThreads);
  29. //int pid = getpid();
  30. bMore = Process32Next(hProcessSnap, &pe32);
  31. if(static_cast<int>(pe32.th32ProcessID) == processID)
  32. {
  33. //qDebug()<<"进程名称 = "<<QString::fromWCharArray(pe32.szExeFile);
  34. //qDebug()<<"进程ID = "<<pe32.th32ProcessID;
  35. //qDebug()<<"线程数量 = "<<pe32.cntThreads;
  36. return static_cast<int>(pe32.cntThreads);
  37. }
  38. }
  39. return -1;
  40. #elif defined(Q_OS_LINUX)
  41. return -1;
  42. #endif
  43. }
  44. bool ThreadUtility::BlockExitThread(QThread *thread, unsigned long msecs)
  45. {
  46. thread->quit();
  47. thread->requestInterruption();
  48. bool isSuccess = false;
  49. if(!thread->wait(msecs))
  50. {
  51. qDebug()<<"线程异常结束"<<thread;
  52. thread->terminate();
  53. if(!thread->wait(20000)) qDebug()<<"线程terminate异常";
  54. }
  55. else
  56. {
  57. qDebug()<<"线程正常结束"<<thread;
  58. isSuccess = true;
  59. }
  60. return isSuccess;
  61. }
  62. /* 工作线程 */
  63. ThreadWorker::ThreadWorker()
  64. : QObject(nullptr)
  65. , m_pWorkTimer(nullptr)
  66. , m_bInited(false)
  67. , m_nInterval(1000)
  68. {
  69. m_pWorkTimer = new QTimer(nullptr);
  70. m_pWorkTimer ->setParent(this);
  71. connect(m_pWorkTimer, &QTimer::timeout, this, &ThreadWorker::OnWorkTimer, Qt::QueuedConnection);
  72. connect(this, &ThreadWorker::sig_StartWorkTimer, this, &ThreadWorker::OnStartWorkTimer, Qt::QueuedConnection);
  73. QThread *pHostThread = new QThread(nullptr);
  74. pHostThread->start();
  75. moveToThread(pHostThread); /* 将本实例移动到新线程中,其实就是将事件循环等移过去 */
  76. m_pWorkTimer->moveToThread(pHostThread); /* 将定时器移到新线程中,定时器触发的槽函数就会运行在新线程中 */
  77. /*----------------------------------------------------------------
  78. * 对线程执行quit会发生: 结束线程的事件循环(线程里的对象不再能接受任何信号, 除了deleteLater), 发送finished信号
  79. * 宿主线程对象和工作对象都在同一个线程, 所以用DirectConnection
  80. * 这里是一个序列: 对线程执行quit -> 线程发送finished信号 -> 工作对象释放 -> 线程对象释放
  81. ----------------------------------------------------------------*/
  82. connect(pHostThread, &QThread::finished, this, &ThreadWorker::deleteLater, Qt::DirectConnection);
  83. connect(this, &ThreadWorker::destroyed, pHostThread, &QThread::deleteLater, Qt::DirectConnection);
  84. WorkerCollector::Instance()->AddWorker(this);
  85. }
  86. ThreadWorker::~ThreadWorker()
  87. {
  88. }
  89. //在子线程执行(m_pWorkTimer已被移至线程)
  90. void ThreadWorker::OnStartWorkTimer(int msecs)
  91. {
  92. m_nInterval = (msecs==-1)?10:msecs;
  93. if(msecs == -1) m_pWorkTimer->setSingleShot(true);
  94. m_pWorkTimer->start(0);
  95. }
  96. //Start方法被主线程调用, 内容在主线程执行
  97. void ThreadWorker::Start(int interval)
  98. {
  99. QMutexLocker lockerInited(&m_mutexInited);
  100. m_bInited = false;
  101. emit sig_StartWorkTimer(interval);
  102. }
  103. void ThreadWorker::NonBlockStop()
  104. {
  105. QThread *pThread = dynamic_cast<QThread*>(thread());
  106. if(pThread == nullptr) return;
  107. pThread->quit();
  108. pThread->requestInterruption();
  109. }
  110. //该方法只能被主线程调用
  111. //否则报错: Thread tried to wait on itself
  112. bool ThreadWorker::BlockStop(unsigned long msecs)
  113. {
  114. return ThreadUtility::BlockExitThread(thread(), msecs);;
  115. }
  116. void ThreadWorker::SetInterval(int interval)
  117. {
  118. m_pWorkTimer->setInterval(interval);
  119. }
  120. //OnWorkTimer在其他线程执行
  121. void ThreadWorker::OnWorkTimer()
  122. {
  123. m_pWorkTimer->setInterval(m_nInterval);
  124. /* 初始化锁 */
  125. m_mutexInited.lock();
  126. if(!m_bInited)
  127. {
  128. m_bInited = true;
  129. DoInit();
  130. }
  131. m_mutexInited.unlock();
  132. DoWork();
  133. emit sig_Ticked(this);
  134. //工作对象非循环且内容执行完毕
  135. if(m_pWorkTimer->isSingleShot())
  136. {
  137. NonBlockStop();
  138. return;
  139. }
  140. //主动调用NonBlockStop或BlockStop且未等待超时
  141. if(thread()->isInterruptionRequested())
  142. {
  143. m_pWorkTimer->stop();
  144. return;
  145. }
  146. }
  147. WorkerCollector::CollectorGarbo WorkerCollector::garbo;
  148. WorkerCollector* WorkerCollector::sm_pInstance = new WorkerCollector(); //初始化静态单例(饿汉)
  149. //在这里释放那些: 直到程序结束还没有被释放的工作对象
  150. WorkerCollector::~WorkerCollector()
  151. {
  152. sm_pInstance = nullptr;
  153. auto pred = [](QPointer<ThreadWorker> x){return x != nullptr;};
  154. QList<QPointer<ThreadWorker>> remainWorkers;
  155. std::copy_if(m_listWorkers.begin(), m_listWorkers.end(), std::back_inserter(remainWorkers), pred);
  156. qDebug() << "线程管理器释放: 待释放工作对象个数" << remainWorkers.count();
  157. int counter = 0;
  158. for(QPointer<ThreadWorker> pWorker: remainWorkers)
  159. {
  160. //注意: 这里如果是停止超时的情况, 说明工作对象正在执行内容, 直接调用delete可能会导致崩溃
  161. //而且这里不能使用deleteLater来释放工作对象, 因为线程的事件循环已经退出了
  162. if(!pWorker->BlockStop(5000)) continue;
  163. delete pWorker;
  164. counter++;
  165. }
  166. qDebug()<<"已释放工作对象: "<<counter;
  167. m_listWorkers.clear();
  168. }
  169. void WorkerCollector::AddWorker(ThreadWorker *worker)
  170. {
  171. QPointer<ThreadWorker> pWorker(worker);
  172. m_listWorkers.append(pWorker);
  173. }