Thread refuses to quit

2019-07-04 08:58发布

问题:

I'm experiencing a problem with QThread::currentThread()->quit();

main.cpp:

#include <QCoreApplication>
#include <QtCore>
#include "myobject.h"

QThread* cThread;
MyObject* cObject;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    cThread = new QThread();
    cObject = new MyObject();
    cObject->moveToThread(cThread);

    QObject::connect(cThread, SIGNAL(started()),
                     cObject, SLOT(doWork()));

    QObject::connect(cThread, SIGNAL(finished()),
                     cThread, SLOT(deleteLater()));

    QObject::connect(cThread, SIGNAL(finished()),
                     cObject, SLOT(deleteLater()));

    cThread->start();

    return a.exec();
}

myobject.cpp:

#include "myobject.h"

MyObject::MyObject(QObject *parent) :
    QObject(parent)
{
}

void MyObject::doWork()
{
    qDebug() << "Hi";
    QThread::currentThread()->quit(); // It is supposed to stop here, but it doesn't.
    for (int i = 0; i < 1000000; i++) {
        qDebug() << i;
    }
}

myobject.h:

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QtCore>

class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = 0);

signals:

public slots:
    void doWork();

};

#endif // MYOBJECT_H

It is supposed to stop in myobject.cpp with QThread::currentThread()->quit(); but it doesn't.

Getting an error saying that this question is too short.

Solution: add "return;" after the quit call.

回答1:

From the documentation of the function exit (which is what quit calls):

Note that unlike the C library function of the same name, this function does return to the caller -- it is event processing that stops

Which means the code you wrote is behaving as it should by going into the loop. You are stopping the event loop of the thread from executing, and that's the only thing quit does. The thread will finish the execution of doWork().

Now it raises an interesting question : will cThread and cObject be deleted? No. An object with deleteLater will be deleted when the control returns to the event loop. But here you just stopped the event loop of the thread, so even if the deleteLater are posted they will not be processed.

Your object will survive and you will have a memory leak. An easy test will be to declare a dummy destructor for MyObject which just prints something and check if it is called.



回答2:

The quit function only will terminate the event loop associated with the thread if you have one.

By default the run method calls the exec method that starts the event loop.

Seeing the the code of the QThread:

emit started
run();

This means that when the started event is emitted your event loop was not started yet because it will only be started inside of the run method. The method quit will only work if the event loop is already started with the exec call.

I hope this can help



标签: c++ qt qt5