前提
针对继承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();
}