| 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 itselfbool 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);}
 |