QThread,thread,rly?

时间:2010-10-12 01:26:11

标签: multithreading qt qt4

有一段时间我现在很狡猾地得到一个大量的时间/ cputime排放动作在一个响应的UI后面运行。不幸的是,我似乎无法让它运行,“我认为”问题是插槽没有在QThread工作器中处理,而是GUI线程。尽管如此,ThreadID仍然有所不同。

我已经读过这个http://doc.trolltech.com/4.6/threads-qobject.html 并使用googel和SO搜索,但没有任何真正帮助我。可能是我看不到的顽固的东西。

下面是我的缩减代码(注意:在与二进制文件相同的文件夹中需要名为“dummy1024x1024.png”的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();
}

dummy.h

#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 个答案:

答案 0 :(得分:5)

正确使用QThread是Qt用户的常见问题。 Qt Labs的blog post很好地解释了这一点。

简而言之,您应该子类QThread来包含您要在该线程中运行的代码。您应该将代码包装在QObject子类中,实例化它并使用QObject::moveToThread将对象移动到QThread上下文中,以便在{{1}的上下文中进行处理}}。然后,您可以在QThread子类中拥有可以安全连接到另一个线程的插槽,但这些插槽将在您期望的上下文中运行。

有些人可能认为,如果您可以轻松地在QObject方法中完成您想要做的事情并且不需要太多(或任何)外部交互,那么子类QThread应该没问题,但即使在此简单的情况我赞成一个单独的类来更好地封装。