在这里问这个问题之前,我想了很多,阅读了很多文章。没有一篇文章给我一个正确的答案。
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
Worker 对象具有新线程的亲和性。
工人完成信号将调用
quit()
线程。这将结束线程的事件循环并启动线程完成信号。工人
finished
信号连接到工人deleteLater()
。根据deleteLater()
文档
计划删除此对象。当控制返回事件循环时,该对象将被删除。如果调用此函数时事件循环没有运行(例如
deleteLater()
,在之前对对象调用过QCoreApplication::exec()
),则一旦启动事件循环,该对象将被删除。请注意,进入和离开新的事件循环(例如,通过打开模式对话框)不会执行延迟删除;对于要删除的对象,控件必须返回到从中
deleteLater()
调用的事件循环。
注意:多次调用该函数是安全的;当第一个延迟删除事件被传递时,该对象的所有未决事件都将从事件队列中删除。**
所以当没有事件循环时,因为线程已经退出并且它已经提出了完成信号,我们将不再再次启动同一个线程。在这种情况下,deleteLater()
将永远不会处理,因为事件循环不存在,并且工作对象根本不会被删除。这不会造成内存泄漏。?
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
如果我们认为交换两条线可以解决问题,那么我还有另一个问题。QT 明确指出发出信号时调用槽的顺序是不确定的
上面提到的文章链接中有一堆评论。甚至作者也无法完全回答这个问题