2010-10-12 2 views
2

на какое-то время я сейчас нахожусь, чтобы получить массовое время работы/cputime, работающее за прекрасно отвечающим интерфейсом. К сожалению, я не могу заставить его работать, и «я думаю», проблема заключается в том, что слот не обрабатывается в рабочем процессе QThread, а в потоке графического интерфейса. Однако ThreadID отличаются как ожидалось.QThread, threaded, rly?

Я уже прочитал это http://doc.trolltech.com/4.6/threads-qobject.html и использовал поиск googel и SO, но ничего не помогло мне. Наверное, что-то упрямое я просто не вижу.

Ниже мой урезывание код (Примечание: PNG под названием "dummy1024x1024.png" требуется в той же папке, как двоичный):

main.cpp

#include <QtGui> 
#include "dummy.h" 

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 
    Dummy d(NULL); 
    d.show(); 
    qDebug() << "App thread " << QThread::currentThreadId(); 
    return app.exec(); 
} 

манекен. ч

#ifndef DUMMY_H 
#define DUMMY_H 

#include <QWidget> 
#include <QVBoxLayout> 
#include <QPushButton> 

#include "workerthread.h" 

class Dummy : public QWidget 
{ 
Q_OBJECT 
public: 
    explicit Dummy(QWidget *parent = 0); 
    virtual ~Dummy(); 
private: 
    QVBoxLayout* m_layout; 
    QPushButton* m_dummy[3]; 
    QPushButton* m_shootcalc; 
    WorkerThread* m_work; 
signals: 

public slots: 

}; 

#endif // DUMMY_H 

dummy.cpp

#include "dummy.h" 

Dummy::Dummy(QWidget *parent) : 
    QWidget(parent) 
{ 
    m_work = new WorkerThread(this); 
    m_work->start(); 

    m_shootcalc = new QPushButton("Calc!", this); 
    connect(m_shootcalc, SIGNAL(clicked()), m_work, SLOT(expensiveCalc()), Qt::QueuedConnection); 

    m_dummy[0] = new QPushButton("Dummy [0]", this); 
    m_dummy[1] = new QPushButton("Dummy [1]", this); 
    m_dummy[2] = new QPushButton("Dummy [2]", this); 

    m_layout = new QVBoxLayout(this); 
    m_layout->addWidget(m_shootcalc); 
    m_layout->addWidget(m_dummy[0]); 
    m_layout->addWidget(m_dummy[1]); 
    m_layout->addWidget(m_dummy[2]); 
    setLayout(m_layout); 
} 


Dummy::~Dummy() 
{ 
    m_work->quit(); 
    m_work->wait(); 
    m_work->deleteLater(); 
    m_work = NULL; 
} 

workerthread.h

#ifndef WORKERTHREAD_H 
#define WORKERTHREAD_H 

#include <QThread> 
#include <QPixmap> 
#include <QDebug> 

class WorkerThread : public QThread 
{ 
Q_OBJECT 
public: 
    explicit WorkerThread(QObject *parent = 0); 
protected: 
    virtual void run(); 
signals: 

public slots: 
    void expensiveCalc(); 
}; 

#endif // WORKERTHREAD_H 

workerthread.cpp

#include "workerthread.h" 

WorkerThread::WorkerThread(QObject *parent) : 
    QThread(parent) 
{ 
} 


void WorkerThread::run() 
{ 
    qDebug() << "Thread start << " << QThread::currentThreadId(); 
    exec(); 
    qDebug() << "Thread stop << " << QThread::currentThreadId(); 
} 

void WorkerThread::expensiveCalc() 
{ 
    qDebug() << "start pixie loading.... " << QThread::currentThreadId(); 
    QPixmap* pixies[16384]; 
    for (int i=0; i<16384; ++i) 
    { 
     pixies[i] = new QPixmap("./dummy1024x1024.png"); 
     if (i>0) 
      delete pixies[i-1]; 
     msleep(1); 
    } 
    delete pixies[16384-1]; 

    qDebug() << "loaded pixies " << QThread::currentThreadId(); 
    qDebug() << ""; 
    qDebug() << ""; 
    qDebug() << ""; 
    qDebug() << ""; 
} 

Спасибо за любую помощь/наконечник/ответ

+1

Некоторое время назад появилась статья в немецком «Linux Magazin» об этой проблеме. И есть некоторый код, доступный в github для workthreads, которые работают правильно с сигналами/слотами. См. Здесь: http://github.com/picaschaf/Qt-Worker-Thread Это может быть то, что вы ищете. – smerlin

+1

Спасибо за эту информацию, я обычно читаю LinuxMagazine, но, похоже, я пропустил это. Я сделал приведенный выше код, основываясь на том, что мне рассказала Документация Qt и примеры. К сожалению, документация QThread является одной из худших частей Qt Doc. – drahnr

ответ

5

Правильное использование QThread является общим проблема среди Qt u ГКР. Это blog post в Qt Labs объясняет это красиво.

Вкратце, вы должны не подкласс QThread, чтобы содержать код, который вы хотите запустить в этой теме. Вы должны обернуть свой код в подкласс QObject, создать его экземпляр и использовать QObject::moveToThread, чтобы переместить ваш объект в контекст QThread, чтобы обработка произошла в контексте этого QThread. Затем вы можете иметь слоты в вашем подклассе QObject, который можно безопасно подключить к другому потоку, но будет работать в ожидаемом вами контексте.

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

+3

и описать реальную проблему: сам QThread qobject живет в основном потоке, а не в самом потоке представляет (!). Разделение, которое описывает Арнольд, должно сделать это более ясным. –

+0

Спасибо, да, объект QThread «живет» в основном потоке, поэтому сигналы к нему обрабатываются в цикле основного события, что и видит OP. –

+0

появилась статья в немецком «Linux Magazin» некоторое время назад об этой проблеме. И есть некоторый код, доступный в github для workthreads, которые работают правильно с сигналами/слотами. См. Здесь: http://github.com/picaschaf/Qt-Worker-Thread Это может быть то, что вы ищете. – smerlin