Qt对象仍然可以在没有事件循环的情况下删除Later()吗?

时间:2014-05-30 13:59:57

标签: c++ qt

我对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()调用仍会发布一个被拾取的事件?

1 个答案:

答案 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);