Мой QThread завершен, но я не могу получить сигнал

Метод запуска моего QThread завершается, но я не могу получить сигнал.

Вот весь код:

Заголовок моей темы:

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QDebug>

#include "mydataobject.h"

class MyThread: public QThread
{
    Q_OBJECT
public:
    MyThread(MyDataObject data,
             bool useData);

private:
    void run();

signals:
    void resultsReady(MyDataObject data);

private:
    MyDataObject data;
    bool useData;
};

#endif // MYTHREAD_H

Код моей темы:

#include "mythread.h"

MyThread::MyThread(MyDataObject data, bool useData)
{
    this->data = data;
    this->useData = useData;
}

void MyThread::run()
{
    if( useData )
    {
        data.calculate(); // Do something
    }

    emit resultsReady(data);
    qDebug() << "Thread finished";
}

Мой тестовый заголовок:

#ifndef THREADTESTER_H
#define THREADTESTER_H

#include <QDebug>
#include "mythread.h"

class ThreadTester: public QObject
{
    Q_OBJECT
public:
    ThreadTester();
    void runTests();

public slots:
    void threadFinished(MyDataObject data);

private:
    MyDataObject data;
};

#endif // THREADTESTER_H

Мой тестовый код:

#include "threadtester.h"

ThreadTester::ThreadTester(){}

void ThreadTester::runTests()
{
    qRegisterMetaType<MyDataObject>("MyDataObject");

    MyDataObject data;
    MyThread* thread = new MyThread(data, true);

    connect(thread, SIGNAL(resultsReady(MyDataObject)),
            this, SLOT(threadFinished(MyDataObject)));

    thread->start();
    thread->wait();
}

void ThreadTester::threadFinished(MyDataObject data)
{
    qDebug() << "TEST";
    this->data = data;
}

Основная функция:

#include <QApplication>

#include "threadtester.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    ThreadTester threadTester;
    threadTester.runTests();

    return a.exec();
}

Почему публичный слот threadFinished никогда не вызывается?

Примечание: появляется сообщение "Поток завершен", а сообщение "ТЕСТ" нет.


person KelvinS    schedule 29.08.2016    source источник
comment
какая версия qt?   -  person Surt    schedule 29.08.2016
comment
Извините, я забыл указать эту информацию. Qt 5.3.2   -  person KelvinS    schedule 29.08.2016
comment
Бьюсь об заклад, у вас нет цикла событий.   -  person Marek R    schedule 29.08.2016
comment
Я подозреваю, что @MarekR только что указал на то же самое. Не могли бы вы дать более подробную информацию о том, как вы создаете ThreadTester, возможно, также показав свой main(), если именно там вы создаете все эти вещи? Кроме того, просто из любопытства, почему вы используете базу QWidget вместо QObject? Это на самом деле виджет в форме (но у вас нет подходящего конструктора для этого, так что...)?   -  person Jason C    schedule 29.08.2016
comment
Спасибо @MarekR и JasonC. Моя ошибка, это не QWidget. Это QObject, я отредактировал вопрос. Я также добавил код основной функции в вопрос. Извините, я не понял, что вы имеете в виду под циклом событий.   -  person KelvinS    schedule 30.08.2016
comment
@KelvinSalton Ваш код, как есть, с добавленным фиктивным MyDataObject для компиляции, отлично работает для меня с Qt 5.3.2 (а также с 4.8.1 с небольшими изменениями). Он печатает оба выходных сообщения.   -  person Jason C    schedule 30.08.2016
comment
Этот код работает просто отлично.   -  person Kuba hasn't forgotten Monica    schedule 30.08.2016
comment
Однако стоит отметить, что цикл событий ThreadTester на самом деле не выполняется во время выполнения этого потока, поскольку вы создаете его в основном потоке, а затем wait() для завершения потока в своем конструкторе, прежде чем позволить программе перейти к a.exec(). Так что на самом деле происходит то, что сигнал ставится в очередь, но не обрабатывается до тех пор, пока не запустится a.exec(), что, вероятно, не то, что вы ожидаете. См. также wiki.qt.io/Threads_Events_QObjects#Events_and_the_event_loop.   -  person Jason C    schedule 30.08.2016
comment
Это странно. В любом случае, я проверю, что может произойти. Если найду решение, отпишусь здесь. Спасибо за помощь.   -  person KelvinS    schedule 30.08.2016


Ответы (1)


Что происходит в вашем коде:

  1. создать QApplication
  2. создать ThreadTester
  3. запустить метод ThreadTester::runTests, который делает следующее:

    • creates tread object
    • подключиться к результату
    • начать нить
    • ждите тред…
    • теперь поток выполняет свою работу и испускает сигнал
    • поскольку вы connect использовали метод подключения по умолчанию, вызов слота планируется запустить в цикле событий, который еще не запущен.
    • поток завершается
    • …дождитесь завершения потока (возможно, здесь вы ожидаете окончательный результат, но посмотрите, что произойдет позже)
  4. цикл событий запущен

  5. цикл событий выполняет поставленный в очередь вызов слота ThreadTester::threadFinished
  6. цикл событий ожидает следующих событий
person Marek R    schedule 30.08.2016