Qt threads - новый способ проверки, пожалуйста

Итак, новичок в Qt. Прочтите книгу по программированию wiki и C++ Gui, и они говорят о подклассе QThread. Обнаружил, что сейчас это не рекомендуется.

Итак, у меня есть некоторый практический код, и у меня есть несколько вопросов о том, правильно ли это. Поэтому я был бы очень признателен, если бы кто-нибудь посмотрел, пожалуйста.

Поэтому я создал класс с QThread в качестве закрытого члена для использования с movetothread. При его создании я старался не указывать родителя. Поэтому мой первый вопрос: это нормально?

Второй вопрос возникает из m_thread->quit(); Я обнаружил, что мое соединение с завершенным не испускалось, пока я не сделал это. Так это правильный путь? Я прочитал http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ и увидел, что соединение между finish и deleteLater в том же потоке, но не на 100% уверен, что это следует использовать с quit.

Наконец, говоря об deleteLater, означает ли это, что мне не нужно удалять m_thread?

Спасибо за любое время.

Код здесь. Простой QDialog с кнопкой. worker.cpp

#include "worker.h"

worker::worker(QObject *parent) :
    QObject(parent)
{
    stopped = false;
}

void worker::setupAndRun()
{
    m_thread = new QThread();
    connect(m_thread,SIGNAL(started()),this,SLOT(doWork()));
    connect(m_thread,SIGNAL(finished()),this,SLOT(onComplete()));
    connect(m_thread,SIGNAL(finished()),m_thread,SLOT(deleteLater()));
    this->moveToThread(m_thread);
    m_thread->start();
}

void worker::doWork()
{

    for(int i = 0; i < 20000; i++)
    {
        if (this->stopped)
            break;
        qDebug() << i << " : " <<  Q_FUNC_INFO << m_thread->currentThreadId();
    }
    // --- I think the quit calls the finished signal?
    m_thread->quit();

}

void worker::onComplete()
{
    qDebug() <<  Q_FUNC_INFO << "Called " << m_thread->currentThreadId();
}

worker.h

#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <QDebug>
#include <QThread>

class worker : public QObject
{
    Q_OBJECT
public:
    explicit worker(QObject *parent = 0);
    void setupAndRun();
signals:

public slots:
    void doWork();
    void onComplete();
private:
    // --- The thread that I use to movetothread with.
    // Is this ok?
    QThread *m_thread;
    bool stopped;
};

#endif // WORKER_H

Кнопка диалогового окна

void Dialog::on_pushButton_clicked()
{
    m_worker = new worker();
    m_worker->setupAndRun();
}

person DannyK    schedule 17.10.2012    source источник


Ответы (1)


С первого взгляда особо ничего не заметил, но кое-что:

Поскольку m_thread является переменной-членом, вы должны обрабатывать ее немного по-другому. Вы можете инициализировать его null в конструкторе, а также установить m_thread = null после вызова m_thread->quit(), так как вскоре после этого он будет удален, и вам не нужен висячий указатель.

С помощью этого кода вы также должны подключить готовый сигнал к m_worker’s deleteLater(), так как, похоже, нет другого кода для его удаления. Вы также должны позаботиться о потоках при выходе из приложения, например, с помощью qAddPostRoutine, так что все потоки завершаются, а все связанные объекты удаляются.

person hyde    schedule 17.10.2012
comment
Привет Хайд. Спасибо за ответ. Но когда я добавляю m_worker в качестве родителя, я получаю сбой после запуска с этим в выводе: QThread::wait: Thread пытался ждать сам себя QThread: уничтожен, пока поток все еще работает Ошибка ASSERT в QMutex::lock: Internal ошибка, время бесконечного ожидания истекло., файл thread/qmutex.cpp, строка 452 - person DannyK; 17.10.2012
comment
Хорошо, если вы не внесли никаких других изменений, возможно, объект потока не может быть дочерним по отношению к QObject с привязкой к нему потока. На всякий случай редактирую свой ответ, избегайте неверной информации... - person hyde; 17.10.2012
comment
Спасибо, Хайд. Цените свое время. - person DannyK; 17.10.2012