threadcontroller.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. connect(m_pWorkTimer, &QTimer::timeout, this, &ThreadWorker::OnWorkTimer, Qt::QueuedConnection);
  71. connect(this, &ThreadWorker::sig_StartWorkTimer, this, &ThreadWorker::OnStartWorkTimer, Qt::QueuedConnection);
  72. QThread *pHostThread = new QThread(nullptr);
  73. pHostThread->start();
  74. moveToThread(pHostThread); /* 将本实例移动到新线程中,其实就是将事件循环等移过去 */
  75. m_pWorkTimer->moveToThread(pHostThread); /* 将定时器移到新线程中,定时器触发的槽函数就会运行在新线程中 */
  76. /*----------------------------------------------------------------
  77. * 对线程执行quit会发生: 结束线程的事件循环(线程里的对象不再能接受任何信号, 除了deleteLater), 发送finished信号
  78. * 宿主线程对象和工作对象都在同一个线程, 所以用DirectConnection
  79. * 这里是一个序列: 对线程执行quit -> 线程发送finished信号 -> 工作对象释放 -> 线程对象释放
  80. ----------------------------------------------------------------*/
  81. connect(pHostThread, &QThread::finished, this, &ThreadWorker::deleteLater, Qt::DirectConnection);
  82. connect(this, &ThreadWorker::destroyed, pHostThread, &QThread::deleteLater, Qt::DirectConnection);
  83. WorkerCollector::Instance()->AddWorker(this);
  84. }
  85. ThreadWorker::~ThreadWorker()
  86. {
  87. }
  88. //在子线程执行(m_pWorkTimer已被移至线程)
  89. void ThreadWorker::OnStartWorkTimer(int msecs)
  90. {
  91. m_nInterval = (msecs==-1)?10:msecs;
  92. if(msecs == -1) m_pWorkTimer->setSingleShot(true);
  93. m_pWorkTimer->start(0);
  94. }
  95. //Start方法被主线程调用, 内容在主线程执行
  96. void ThreadWorker::Start(int interval)
  97. {
  98. QMutexLocker lockerInited(&m_mutexInited);
  99. m_bInited = false;
  100. emit sig_StartWorkTimer(interval);
  101. }
  102. void ThreadWorker::NonBlockStop()
  103. {
  104. QThread *pThread = dynamic_cast<QThread*>(thread());
  105. if(pThread == nullptr) return;
  106. pThread->quit();
  107. pThread->requestInterruption();
  108. }
  109. //该方法只能被主线程调用
  110. //否则报错: Thread tried to wait on itself
  111. bool ThreadWorker::BlockStop(unsigned long msecs)
  112. {
  113. return ThreadUtility::BlockExitThread(thread(), msecs);;
  114. }
  115. void ThreadWorker::SetInterval(int interval)
  116. {
  117. m_pWorkTimer->setInterval(interval);
  118. }
  119. //OnWorkTimer在其他线程执行
  120. void ThreadWorker::OnWorkTimer()
  121. {
  122. m_pWorkTimer->setInterval(m_nInterval);
  123. /* 初始化锁 */
  124. m_mutexInited.lock();
  125. if(!m_bInited)
  126. {
  127. m_bInited = true;
  128. DoInit();
  129. }
  130. m_mutexInited.unlock();
  131. DoWork();
  132. emit sig_Ticked(this);
  133. //工作对象非循环且内容执行完毕
  134. if(m_pWorkTimer->isSingleShot())
  135. {
  136. NonBlockStop();
  137. return;
  138. }
  139. //主动调用NonBlockStop或BlockStop且未等待超时
  140. if(thread()->isInterruptionRequested())
  141. {
  142. m_pWorkTimer->stop();
  143. return;
  144. }
  145. }
  146. WorkerCollector::CollectorGarbo WorkerCollector::garbo;
  147. WorkerCollector* WorkerCollector::sm_pInstance = new WorkerCollector(); //初始化静态单例(饿汉)
  148. //在这里释放那些: 直到程序结束还没有被释放的工作对象
  149. WorkerCollector::~WorkerCollector()
  150. {
  151. sm_pInstance = nullptr;
  152. auto pred = [](QPointer<ThreadWorker> x){return x != nullptr;};
  153. QList<QPointer<ThreadWorker>> remainWorkers;
  154. std::copy_if(m_listWorkers.begin(), m_listWorkers.end(), std::back_inserter(remainWorkers), pred);
  155. qDebug() << "线程管理器释放: 待释放工作对象个数" << remainWorkers.count();
  156. int counter = 0;
  157. for(QPointer<ThreadWorker> pWorker: remainWorkers)
  158. {
  159. //注意: 这里如果是停止超时的情况, 说明工作对象正在执行内容, 直接调用delete可能会导致崩溃
  160. //而且这里不能使用deleteLater来释放工作对象, 因为线程的事件循环已经退出了
  161. if(!pWorker->BlockStop(5000)) continue;
  162. delete pWorker;
  163. counter++;
  164. }
  165. qDebug()<<"已释放工作对象: "<<counter;
  166. m_listWorkers.clear();
  167. }
  168. void WorkerCollector::AddWorker(ThreadWorker *worker)
  169. {
  170. QPointer<ThreadWorker> pWorker(worker);
  171. m_listWorkers.append(pWorker);
  172. }