| 
					
				 | 
			
			
				@@ -0,0 +1,190 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 |