QThread никогда не запускается / не заканчивается до того, как его можно будет использовать? - PullRequest
2 голосов
/ 23 апреля 2011

Я создал собственный класс QObject с именем EncodeThread, который выглядит следующим образом:

class EncodeThread : public QObject {
    Q_OBJECT

public:
    void set(SWSL::Video* v, QStringList f, QDir vDir);
    void run();

public slots:
    void encode();

signals:
    void encodeProgress(int i);

private:
    SWSL::Video* video;
    QStringList files;
    QDir videoDir;
};

Как может быть очевидно, этот класс используется для кодирования видео с использованием внешней библиотеки. Encode () содержит актуальную подпрограмму кодирования, run () - это функция, которую я добавил при устранении неполадок, хотя она явно не работает:

void EncodeThread::run() {
    if (currentThread() != this) {
        // caller is in different thread.
        QMetaObject::invokeMethod(this, "encode", Qt::QueuedConnection);
    }
    else {
        encode();
    }
}

Проблема заключается в том, что я использую функцию QThread и moveToThread () в экземпляре EncodeThread, а именно, что, кажется, ничего не происходит. Данные не записываются, и экземпляр никогда не генерирует сигнал, который должен сохранить закодированный файл на диск.

encThread.set(video, files, videoDir);
connect(&encThread, SIGNAL(encodeProgress(int)), cookVideoProgress, SLOT(setValue(int)));
    connect(&encThread, SIGNAL(finished()), this, SLOT(videoCookEnd()));
    connect(this, SIGNAL(videoEncode()), &encThread, SLOT(encode()));
encThread.moveToThread(&thread);
    thread.start();

Выше показано, как запускается вся установка. Переменные EncThread и thread объявлены в классе MainWindow. Я сделал функцию set () для вызова EncodeThread encode () после попыток вызвать encode () из основного потока, используя сигналы и QMetaObject не удалось.

Я не новичок в многопоточности, поскольку использовал нативные потоки Windows и Linux, а также различные межплатформенные реализации, но QThreads действительно, кажется, сбивает меня с толку. Любые предложения приветствуются:)

Ответы [ 2 ]

1 голос
/ 06 мая 2011

Возможно, поздно будет вам какая-то помощь, но вот небольшая демонстрационная программа, которая запускает класс EncoderThread.Вероятно, он не совсем совпадает с вашим дизайном (в котором ваш вопрос содержал только фрагменты), но демонстрирует запуск экземпляра объекта в своем собственном потоке и подключение двух объектов в разных потоках через сигналы / слоты, чтобы позволить им общаться:

#include <stdio.h>
#include <QObject>
#include <QThread>
#include <QtCore/QCoreApplication>

// QSleeper is just a toy utility class that makes the
//  protected QThread::sleep() family of functions
//  publicly accessible.  It's only use is for demo
//  programs like this
class Sleeper : QThread
{
public:
    static void sleep(unsigned long secs) { QThread::sleep(secs); }
    static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
    static void usleep(unsigned long usecs) { QThread::usleep(usecs); }

};


// an Encoder class that maintains itself on is own thread
class EncodeThread : public QObject {
    Q_OBJECT

public:
    EncodeThread();

public slots:
    void encode();

signals:
    void encodeProgress(int i);
    void finished();

private:
    QThread myThread;
};

EncodeThread::EncodeThread() {
    moveToThread(&myThread);
    myThread.start();
}


void EncodeThread::encode()
{
    printf("EncodeThread::encode() on thread %u\n", (unsigned int) QThread::currentThreadId());

    for (int i = 0; i < 6; ++i) {
        // encode for 1 second or so
        printf("EncodeThread::encode() working on thread %u\n", (unsigned int) QThread::currentThreadId());
        Sleeper::sleep(1);
        emit encodeProgress(i);
    }

    emit finished();
    printf("EncodeThread::encode() - done\n");
}




// a controller to manage and monitor an EncoderThread instance
class VideoEncoderController : public QObject
{
    Q_OBJECT
public:
    void start();

public slots:
    void setValue(int);
    void encodingDone();

signals:
    void encodingBegin();
};

void VideoEncoderController::start()
{
    printf("VideoEncoderController::start() on thread %u\n", (unsigned int) QThread::currentThreadId());
    emit encodingBegin();
}

void VideoEncoderController::setValue(int x)
{
    printf("VideoEncoderController::setValue(int %d) on thread %u\n", x, (unsigned int) QThread::currentThreadId());
}

void VideoEncoderController::encodingDone()
{
    printf("VideoEncoderController::encodingDone() on thread %u\n", (unsigned int) QThread::currentThreadId());
}




// a demo program that wires up a VideoEncoderController object to
//  an EncoderThread
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    EncodeThread encThread;
    VideoEncoderController controller;

    QObject::connect(&encThread, SIGNAL(encodeProgress(int)), &controller, SLOT(setValue(int)));
    QObject::connect(&encThread, SIGNAL(finished()), &controller, SLOT(encodingDone()));
    QObject::connect(&controller, SIGNAL(encodingBegin()), &encThread, SLOT(encode()));

    printf("hello world on thread %u\n", (unsigned int) QThread::currentThreadId ());

    controller.start();

    return a.exec();
}



#include "main.moc"
0 голосов
/ 24 апреля 2011

Вы должны получить QThread, а не QObject.Метод run () является абстрактным методом QThread.

...