调用QThread的wait()方法时,报警:QThread::wait: Thread tried to wait on itself
原因:在自己的线程中调用线程的wait()方法。
解决方法:在线程外的其他线程中,调用线程的wait()方法。
示例代码如下:
MyObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include <QThread>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = nullptr);
~MyObject();
void init();
void quitThread();
void test1();
public Q_SLOTS:
void slotTest();
private:
QThread *m_thread = nullptr;
};
#endif // MYOBJECT_H
MyObject.cpp
#include "MyObject.h"
#include <qdebug.h>
MyObject::MyObject(QObject *parent) : QObject(parent)
{
init();
}
MyObject::~MyObject()
{
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
quitThread();
}
void MyObject::init()
{
m_thread = new QThread();
connect(m_thread, &QThread::finished, m_thread, &QThread::deleteLater);
connect(m_thread, &QThread::finished, this, [] {
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
});
moveToThread(m_thread); // 将该对象移入线程中
m_thread->start();
}
void MyObject::quitThread()
{
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
if (m_thread) {
m_thread->quit();
m_thread->wait();
}
}
void MyObject::test1()
{
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
}
void MyObject::slotTest()
{
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
}
创建一个对话框,在对话框中测试:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include "MyObject.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
void init();
private:
QPushButton *m_btnTest = nullptr;
QPushButton *m_btnRelease = nullptr;
MyObject *m_obj = nullptr;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <qboxlayout.h>
#include <qthread.h>
#include <qdebug.h>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
init();
}
Dialog::~Dialog()
{
}
void Dialog::init()
{
setWindowTitle("线程测试");
setFixedSize(360, 160);
m_btnTest = new QPushButton("测试", this);
m_btnTest->setFixedSize(100, 36);
m_btnRelease = new QPushButton("释放对象", this);
m_btnRelease->setFixedSize(100, 36);
m_obj = new MyObject(); // 不需指定父对象
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
QHBoxLayout *lay = new QHBoxLayout(this);
lay->addWidget(m_btnTest);
lay->addWidget(m_btnRelease);
connect(m_btnTest, &QPushButton::clicked, this, [this] {
if (m_obj) {
m_obj->test1();
QMetaObject::invokeMethod(m_obj, "slotTest", Qt::QueuedConnection);
}
});
connect(m_btnRelease, &QPushButton::clicked, this, [this] {
if (m_obj) {
m_obj->deleteLater();
m_obj = nullptr;
}
});
}
运行界面如下:
点击【测试】按钮,打印信息如下所示:
void Dialog::init() 0x43f4
void MyObject::test1() 0x43f4
void MyObject::slotTest() 0x2790
由此可见,主线程的线程ID为0x43f4,子线程的线程ID为0x2790
点击【释放对象】按钮,打印信息如下所示:
virtual MyObject::~MyObject() 0x2790
void MyObject::quitThread() 0x2790
QThread::wait: Thread tried to wait on itself
由于使用的是MyObjec::deleteLater()函数,MyObjectt的析构函数是在子线程中执行的,子线程的退出也是在子线程中执行的,因而报警,且线程退出失败(没有执行QThread::finished)
代码修正:在释放MyObjec对象时,使用delete m_obj,代码如下:
connect(m_btnRelease, &QPushButton::clicked, this, [this] {
if (m_obj) {
delete m_obj;
m_obj = nullptr;
}
});
点击【测试】和【释放对象】按钮时,打印信息如下:
void Dialog::init() 0x1460
void MyObject::test1() 0x1460
void MyObject::slotTest() 0x644
virtual MyObject::~MyObject() 0x1460
void MyObject::quitThread() 0x1460
MyObject::init()::<lambda()> 0x644
由此可见,子线程的退出操作是在主线程中完成的,不仅没有报错,而且线程也成功退出了(执行了线程退出槽函数)
资源文件下载链接(免费):
https://download.csdn.net/download/ouyangxiaozi/89616335