Qt官方文档的方法
QThread创建在栈上,然后QObject需要配合QThread释放资源
直接上代码。结束的时候线程quit and wait
直接上代码
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
~Controller() {
workerThread.quit();
workerThread.wait();
}
上了关键核心代码。
直接按照顺序来说。
1.观察析构函数
~Controller() {
workerThread.quit();
workerThread.wait();
}
一步步来
工作线程quit跟wait退出结束,发出finished信号。
2. 线程退出
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
1
线程退出通知QObject对象删除
3. QThread释放
由于QThread在栈上,所以会自己销毁。
这三部完美的释放了线程资源。
我的做法
我上面讲的第二种方法实际上一开始写的并不好,虽说你把我的代码QObject跟QThraed加上析构函数输出发现也会释放,但是还是会有一些小问题。感谢知乎大佬指出来了。我直接上正确的结论。
工程代码在这里
https://github.com/CryFeiFei/Qt_Teach/tree/master/Qt_Teach/Thread2
我的QThread是放到堆上的。即下面的KThread
直接上我的代码。
m_workerThread = new KThread();
WorkThread* worker = new WorkThread();
worker->moveToThread(m_workerThread);
//等工作的QObject结束,让线程停止结束
connect(worker, &WorkThread::workFinished, m_workerThread, [this]()
{
m_workerThread->quit();
m_workerThread->wait();
});
//线程停止发给QObject让他自己销毁。
connect(m_workerThread, &QThread::finished, worker, &WorkThread::deleteLater);
// QObject销毁之后,让线程自己销毁。
connect(worker, &WorkThread::destroyed, m_workerThread, &QThread::deleteLater);
解释都在备注上。
对比Qt官方的文档,也就是把QThread申请放到了堆上,然后多了一步释放QThread的操作。
即
// QObject销毁之后,让线程自己销毁。
connect(worker, &WorkThread::destroyed, m_workerThread, &QThread::deleteLater);
有兴趣可以自己下载代码调试下,会发现KThread跟worker的析构函数都完美释放了。
释放线程资源必须要做的(避免死锁
一定要等线程停止之后,再销毁线程
QWaitCondition
一定要等线程停止之后,再销毁线程
生产者消费者是用QWaitCondition来进行同步的。
现在我想手动把这个流程停掉
大概有这么几种情况。
比如生产者生产过快,还在wait,这时候我们的线程需要马上停止。
生产者线程在这里wait
if (listBuffer.size() == bufferSize)
{
bufferNotFull.wait(&mutex);
}
这时候是没有办法把生产者停掉的,如果强行delete,那就未知了,运气好,不崩溃,运气差,就crash了。
再看看我们的控制代码是在上面这段代码之前的。
while(1)
{
//xxxxxxx
if (m_bPause)
{
emit workPause();
continue;
}
//..................
//xxxxx
if (listBuffer.size() == bufferSize)
{
bufferNotFull.wait(&mutex);
}
//xxxxxxx
}
也就是这里死锁之后,我们的生产者是永远停不了的。
同理,消费者过快也会出现这个问题。
所以需要我们在释放这种资源的时候要手动调用下两个条件变量的
xxxx.wakeAll();
xxxx.wakeAll();
这样能够避免线程释放资源发生死锁。导致crash。
还有一个方法。
QWaitCondition 的wait是有一个超时时间的,你可以设定一个超时时间,这样就会进入下一次循环,也会避免死锁了。逃)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)