前提
- 针对继承QThread类,重写run接口方式创建的多线程
线程退出
-
对于正在运行的线程,如果想要退出,QT5提供了封装好的接口:requestInterruption和isInterruptionRequested。不再需要自定义互斥量和bool类型的退出标记。
- 退出之前调用requestInterruption,在线程内部的循环操作前判断isInterruptionRequested是否需要退出
-
不要使用terminate接口,可能会引起未知错误
-
配合调用quit和wait接口,使线程真正退出
if (pThread->isRunning()) { pThread->requestInterruption(); pThread->quit(); pThread->wait(); } void run() { while(1) { if (this->isInterruptionRequested()) { return; } // TODO } }
线程暂停和继续
-
使用自定义互斥量和bool类型的暂停标记
- 定义两个互斥量,一个互斥量用于保护暂停标记,另一个用于保护具体操作
- 暂停标记的保护可以使用互斥锁简化操作
-
对外提供暂停、继续、是否暂停三个接口
- 暂停接口修改暂停标记变量,内部循环前判断暂停变量值,如果需要暂停,则QWaitCondition的wait接口阻塞线程;
- 继续接口修改暂停标记标记,同时使用QWaitCondition的wakeall接口唤醒所有等待的线程
- 是否暂停接口可以让客户端知道当前线程是否处于暂停状态。
-
暂停后如果想退出线程,必须先继续线程才能退出
void Pause() { QMutexLocker locker(&m_mutexPause); m_bPaused = true; } void Resume() { QMutexLocker locker(&m_mutexPause); m_bPaused = false; m_WaitCondition.wakeAll(); } bool IsPaused() { return m_bPaused; } void run() { while(1) { m_mutexRun.lock(); if (m_bPaused) { m_WaitCondition.wait(&m_mutexRun); } // TODO m_mutexRun.unlock(); } } if (pThread->isRunning()) { if (pThread->IsPaused()) { pThread->Resume(); } pThread->requestInterruption(); pThread->quit(); pThread->wait(); }