Q阅读相关问题

QThread related problems

本文关键字:问题      更新时间:2023-10-16

我有一些关于QThread的问题和疑问。1)当我使用QThread->quit()时,没有发出finish()信号。2)如何正确构建和完成线程的执行?

1)完成的信号代码 - 头文件。

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class MyThread: public QThread
{
     Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
signals:
public slots:
    void finished();
protected:
    void run();
};
#endif // MYTHREAD_H

1) CPP 文件。

#include "MyThread.h"
MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
}
void MyThread::finished()
{
    //never gets called...
    qDebug() << "Finished.";
}
void MyThread::run()
{
    connect(this, SIGNAL(finished()), this, SLOT(finished()), Qt::DirectConnection);
    this->exec();
}

我正在用这个构建它:

MyThread *mThread = new MyThread(this); //What does parent do/mean ?
mThread->start();
Sleep(5000); //Windows.
mThread->quit(); //Finish thread.

我什至不明白Qt::D irectConnection是做什么的,我已经阅读了文档,但我真的不知道如何使用直接/排队连接。

刚才我想到的另一个问题。

1)如何从自身完成和清理线程?(我的意思是,线程应该自行退出并进行清理。

2)如何正确创建/运行新线程的原因以及为什么?

谢谢。

不要子类QThread . 相反,创建一个工作器对象(继承QObject),创建一个QThread,然后在工作器对象上调用moveToThread()方法。

class Worker : public QObject
{
  Q_OBJECT
public:
  Worker( QObject * parent = 0 )
    : QObject( parent )
  {
    connect( this, SIGNAL(done()), 
             this, SLOT(deleteLater())
            );
  }
public slots:
  void doWork() { // work, work }
signals:
  void done();  // emit this when you're finished with the work
};
// in your main function (or wherever)
QThread * thread = new QThread();
Worker * w = new Worker();
w->moveToThread( thread );
thread->start();
// clean up your thread
QObject::connect( w, SIGNAL(destroyed()), thread, SLOT(quit()) );
QObject::connect( thread, SIGNAL(finished()), thread(deleteLater()) );
// at some point, emit a signal connected to your workers 'doWork()' slot.
// when the work is finished, the worker and thread will both clean themselves up.

编辑:如果我使用的是旧版本的Qt怎么办?

在最近的Qt版本中,QThread::run()方法的默认实现是调用exec(),这将启动线程的事件循环。 如果你支持旧版本的Qt,你确实需要对QThread进行子类化,以便上面的代码工作。

class MyThread : public QThread
{
  void run() { exec(); }
};

然后,只需使用 MyThread 而不是 QThread ,以上所有内容仍然适用。 在这种情况下,子类QThread是完全有意义的,因为您正在创建一个专门的线程类(当您调用 start() 时运行自己的事件循环的线程类)。

至于线程清理,上述内容仍然适用。

QObject::connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()) );

当你调用MyThread::quit()时,事件循环将返回,run()将返回,然后线程对象发出finished()信号。 由于MyThread对象实际上存在于主事件循环中,因此仍将传递deleteLater()槽调用。