Почему не вызывается деструктор этого класса? - PullRequest
0 голосов
/ 23 октября 2011

У меня есть два класса - один работает в главном потоке и выполняет операции с графическим интерфейсом, а другой выполняет некоторые вычисления и выполняет сетевые запросы.

// A member of the class that runs in the main thread
QThread thread;

Вот фрагмент кода метода инициализации классакоторый запускается в основном потоке:

// Create the class that runs in the other thread and move it there
CServerThread * server = new CServerThread;
server->moveToThread(&thread);

// When the thread terminates, we want the object destroyed
connect(&thread, SIGNAL(finished()), server, SLOT(deleteLater()));
thread.start();

В деструкторе для класса, который выполняется в основном потоке:

if(thread.isRunning())
{
    thread.quit();
    thread.wait();
}

То, что я ожидаю, произойдет, когда поток завершит работу и уничтожитэкземпляр класса CServerThread.Однако деструктор для класса CServerThread не вызывается.

1 Ответ

5 голосов
/ 23 октября 2011

QThread::quit() останавливает цикл обработки событий для этого потока.

Сообщает о выходе из цикла потока с кодом возврата 0 (успех).

Но QObject::deleteLater() нуждается в цикле событий, чтобы «собственный» поток был активен:

Запланирует удаление этого объекта.
Объект будет удален, когда управление вернется в цикл обработки событий.

Таким образом, деструктор вашего объекта не будет работать, сигнал finished срабатывает слишком поздно для этого.

Рассмотрим надуманный пример ниже:

#include <QThread>
#include <iostream>

class T: public QObject
{
    Q_OBJECT

    public:
        QThread thr;
        T() {
            connect(&thr, SIGNAL(finished()), this, SLOT(finished()));
        };
        void start() {
            thr.start();
            std::cout << "Started" << std::endl;
        }
        void stop() {
            thr.quit();
            std::cout << "Has quit" << std::endl;
        }
        void end() {
            thr.wait();
            std::cout << "Done waiting" << std::endl;
        }
    public slots:
        void finished() {
            std::cout << "Finished" << std::endl;
        }
};

Если вы позвоните:

T t;
t.start();
t.stop();
t.end();

Вывод будет:

Started
Has quit
Done waiting
Finished

finished срабатывает после выполнения wait. Слишком поздно для того, чтобы ваше deleteLater соединение вступило в силу, цикл событий этого потока уже мертв.

...