QThread,thread,rly?

dra*_*hnr 2 qt multithreading qt4

一段时间以来,我现在非常繁琐,以便在一个响应良好的UI后面运行一个大量的时间/ cputime排放操作.不幸的是,我似乎无法让它运行,"我认为"问题是插槽没有在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();
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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() << "";
}
Run Code Online (Sandbox Code Playgroud)

感谢您的任何帮助/提示/回复

Arn*_*nce 5

正确使用QThread是Qt用户的常见问题.Qt Labs的这篇博文很好地解释了它.

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

有些人可能会争辩说,QThread如果您可以轻松地在run()方法内部完成您想要做的事情并且不需要太多(或任何)外部交互,那么子类化应该没问题,但即使在这个简单的情况下,我也倾向于使用单独的类来实现更好的封装.

  • 并描述实际问题:QThread qobject本身存在于主线程中,而不是线程本身代表(!).阿诺德所描述的分离应该更清楚. (3认同)