我对Qt中的线程和事件循环感到困惑。
QThread通常在exec()
中运行run()
。但是当你覆盖run()
时,就不会有事件循环。
This (older) doc声明在没有事件循环的线程中创建的对象上调用deleteLater()
不起作用:
如果没有运行事件循环,则不会将事件传递给对象。 例如,如果在线程中创建QTimer对象但从不调用 exec(),QTimer永远不会发出timeout()信号。调用 deleteLater()也不会工作。 (这些限制适用于主要 线程也是如此。)
但是,请查看以下代码:
class MyObject : public QObject
{
Q_OBJECT
QString content;
public:
MyObject(QObject *parent = 0);
~MyObject();
};
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void run();
signals:
public slots:
};
MyObject::MyObject(QObject *parent) :
QObject(parent),
content("foobar")
{}
MyObject::~MyObject()
{
// This code is still executed before I close the program. How?
qDebug() << "Destroying MyObject";
}
MyThread::MyThread(QObject *parent) :
QThread(parent)
{}
void MyThread::run()
{
// Creating a heap object in a thread that does not have
// an event loop (because I reimplemented run()).
MyObject * objectification = new MyObject();
sleep(1);
objectification->deleteLater();
}
那么为什么deletelater()
调用仍会发布一个被拾取的事件?
答案 0 :(得分:6)
Qt docs state for deleteLater: -
从Qt 4.8开始,如果在一个没有运行事件循环的线程中的对象上调用deleteLater(),则在线程完成时该对象将被销毁。
当没有事件循环时,仍然会删除该对象。如果您查看source code的QObject :: deleteLater,您会看到发布了一个事件: -
void QObject::deleteLater()
{
QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
那么,让我们看一下when a thread is deleted会发生什么。 QThreadData的析构函数包括: -
for (int i = 0; i < postEventList.size(); ++i) {
const QPostEvent &pe = postEventList.at(i);
if (pe.event) {
--pe.receiver->d_func()->postedEvents;
pe.event->posted = false;
delete pe.event;
}
}
正如我们所见,虽然没有事件循环,但事件列表仍然可用。
如果我们仔细查看QThreadPrivate(仅以一个平台为例,在本例中为unix),您将看到当线程完成时,它转发所有延迟删除的消息,因此它们可以继续处理:
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);