123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- #include "threadcontroller.h"
- #include <QDebug>
- #if defined(Q_OS_WIN32)
- #include <windows.h>
- #include <tlhelp32.h>
- #endif
- #include <QPointer>
- /* 获取线程数 */
- int ThreadUtility::GetThreadCount(int processID)
- {
- #if defined(Q_OS_WIN32)
- PROCESSENTRY32 pe32;
- pe32.dwSize = sizeof(pe32);
-
- HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
- if (hProcessSnap == INVALID_HANDLE_VALUE)
- {
- qDebug()<<"CreateToolhelp32Snapshot 调用失败";
- return -1;
- }
- BOOL bMore = ::Process32First(hProcessSnap, &pe32);
-
- //printf("%-30s %-20s %-20s %-15s\n","szExeFile","th32ProcessID","th32ParentProcessID","cntThreads");
- while(bMore)
- {
- //printf("%-30s ",pe32.szExeFile);
- //printf("%-20d ",pe32.th32ProcessID);
- //printf("%-20d",pe32.th32ParentProcessID);
- ////显示进程的线程数
- //printf("%-15d\n",pe32.cntThreads);
- //int pid = getpid();
- bMore = Process32Next(hProcessSnap, &pe32);
- if(static_cast<int>(pe32.th32ProcessID) == processID)
- {
- //qDebug()<<"进程名称 = "<<QString::fromWCharArray(pe32.szExeFile);
- //qDebug()<<"进程ID = "<<pe32.th32ProcessID;
- //qDebug()<<"线程数量 = "<<pe32.cntThreads;
- return static_cast<int>(pe32.cntThreads);
- }
- }
- return -1;
- #elif defined(Q_OS_LINUX)
- return -1;
- #endif
- }
- bool ThreadUtility::BlockExitThread(QThread *thread, unsigned long msecs)
- {
- thread->quit();
- thread->requestInterruption();
- bool isSuccess = false;
- if(!thread->wait(msecs))
- {
- qDebug()<<"线程异常结束"<<thread;
- thread->terminate();
- if(!thread->wait(20000)) qDebug()<<"线程terminate异常";
- }
- else
- {
- qDebug()<<"线程正常结束"<<thread;
- isSuccess = true;
- }
- return isSuccess;
- }
- /* 工作线程 */
- ThreadWorker::ThreadWorker()
- : QObject(nullptr)
- , m_pWorkTimer(nullptr)
- , m_bInited(false)
- , m_nInterval(1000)
- {
- m_pWorkTimer = new QTimer(nullptr);
- connect(m_pWorkTimer, &QTimer::timeout, this, &ThreadWorker::OnWorkTimer, Qt::QueuedConnection);
- connect(this, &ThreadWorker::sig_StartWorkTimer, this, &ThreadWorker::OnStartWorkTimer, Qt::QueuedConnection);
-
- QThread *pHostThread = new QThread(nullptr);
- pHostThread->start();
- moveToThread(pHostThread); /* 将本实例移动到新线程中,其实就是将事件循环等移过去 */
- m_pWorkTimer->moveToThread(pHostThread); /* 将定时器移到新线程中,定时器触发的槽函数就会运行在新线程中 */
- /*----------------------------------------------------------------
- * 对线程执行quit会发生: 结束线程的事件循环(线程里的对象不再能接受任何信号, 除了deleteLater), 发送finished信号
- * 宿主线程对象和工作对象都在同一个线程, 所以用DirectConnection
- * 这里是一个序列: 对线程执行quit -> 线程发送finished信号 -> 工作对象释放 -> 线程对象释放
- ----------------------------------------------------------------*/
- connect(pHostThread, &QThread::finished, this, &ThreadWorker::deleteLater, Qt::DirectConnection);
- connect(this, &ThreadWorker::destroyed, pHostThread, &QThread::deleteLater, Qt::DirectConnection);
-
- WorkerCollector::Instance()->AddWorker(this);
- }
- ThreadWorker::~ThreadWorker()
- {
-
- }
- //在子线程执行(m_pWorkTimer已被移至线程)
- void ThreadWorker::OnStartWorkTimer(int msecs)
- {
- m_nInterval = (msecs==-1)?10:msecs;
- if(msecs == -1) m_pWorkTimer->setSingleShot(true);
- m_pWorkTimer->start(0);
- }
- //Start方法被主线程调用, 内容在主线程执行
- void ThreadWorker::Start(int interval)
- {
- QMutexLocker lockerInited(&m_mutexInited);
- m_bInited = false;
- emit sig_StartWorkTimer(interval);
- }
- void ThreadWorker::NonBlockStop()
- {
- QThread *pThread = dynamic_cast<QThread*>(thread());
- if(pThread == nullptr) return;
- pThread->quit();
- pThread->requestInterruption();
- }
- //该方法只能被主线程调用
- //否则报错: Thread tried to wait on itself
- bool ThreadWorker::BlockStop(unsigned long msecs)
- {
- return ThreadUtility::BlockExitThread(thread(), msecs);;
- }
- void ThreadWorker::SetInterval(int interval)
- {
- m_pWorkTimer->setInterval(interval);
- }
- //OnWorkTimer在其他线程执行
- void ThreadWorker::OnWorkTimer()
- {
- m_pWorkTimer->setInterval(m_nInterval);
- /* 初始化锁 */
- m_mutexInited.lock();
- if(!m_bInited)
- {
- m_bInited = true;
- DoInit();
- }
- m_mutexInited.unlock();
- DoWork();
- emit sig_Ticked(this);
- //工作对象非循环且内容执行完毕
- if(m_pWorkTimer->isSingleShot())
- {
- NonBlockStop();
- return;
- }
- //主动调用NonBlockStop或BlockStop且未等待超时
- if(thread()->isInterruptionRequested())
- {
- m_pWorkTimer->stop();
- return;
- }
- }
- WorkerCollector::CollectorGarbo WorkerCollector::garbo;
- WorkerCollector* WorkerCollector::sm_pInstance = new WorkerCollector(); //初始化静态单例(饿汉)
- //在这里释放那些: 直到程序结束还没有被释放的工作对象
- WorkerCollector::~WorkerCollector()
- {
- sm_pInstance = nullptr;
- auto pred = [](QPointer<ThreadWorker> x){return x != nullptr;};
- QList<QPointer<ThreadWorker>> remainWorkers;
- std::copy_if(m_listWorkers.begin(), m_listWorkers.end(), std::back_inserter(remainWorkers), pred);
- qDebug() << "线程管理器释放: 待释放工作对象个数" << remainWorkers.count();
- int counter = 0;
- for(QPointer<ThreadWorker> pWorker: remainWorkers)
- {
- //注意: 这里如果是停止超时的情况, 说明工作对象正在执行内容, 直接调用delete可能会导致崩溃
- //而且这里不能使用deleteLater来释放工作对象, 因为线程的事件循环已经退出了
- if(!pWorker->BlockStop(5000)) continue;
- delete pWorker;
- counter++;
- }
- qDebug()<<"已释放工作对象: "<<counter;
- m_listWorkers.clear();
- }
- void WorkerCollector::AddWorker(ThreadWorker *worker)
- {
- QPointer<ThreadWorker> pWorker(worker);
- m_listWorkers.append(pWorker);
- }
|