我对Qt中的线程和事件循环感到困惑.
一个QThread的正常运行exec()在run().但是当你覆盖时run(),就不会有事件循环.
这个(较旧的)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();
}
Run Code Online (Sandbox Code Playgroud)
那么为什么这个deletelater()电话仍然会发布一个被接收的事件?
从Qt 4.8开始,如果在一个没有运行事件循环的线程中的对象上调用deleteLater(),则在线程完成时将销毁该对象.
当没有事件循环时,仍然会删除该对象.如果查看QObject :: deleteLater 的源代码,您会看到发布了一个事件: -
void QObject::deleteLater()
{
QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
Run Code Online (Sandbox Code Playgroud)
那么,让我们看一下删除线程时会发生什么.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;
}
}
Run Code Online (Sandbox Code Playgroud)
如我们所见,虽然没有事件循环,但事件列表仍然可用.
如果我们更仔细地查看QThreadPrivate(仅以一个平台为例,在本例中为unix),您将看到当线程完成时,它会转发所有延迟删除的消息,以便继续处理它们:
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
857 次 |
| 最近记录: |