自定义类moveToThread

实现方式:定义QObject派生类,然后将其对象move到QThread中

class Worker : public QObject
{
  Q_OBJECT

public:
    explicit Worker(QObject *parent = nullptr) : QObject(parent), m_isStop(false) {}
	~Worker() { qDebug() << "Worker destroyed in thread" << QThread::currentThreadId(); }
	void stop() { m_isStop = true; }
	
public slots:
  void doWork(const QString ¶meter) {
	  QString result;
	  if(!m_isStop) {
		  
		  /* ... here is the expensive or blocking operation ... */
		  emit resultReady(result);		  
	  }
  }

signals:
  void resultReady(const QString &result);
  
private:
    bool m_isStop;
};

class Controller : public QObject
{
  Q_OBJECT
  QThread workerThread;
public:
  Controller() {
	  //不要给对象指定父对象
	  Worker *worker = new Worker;
	  
	  // 将Worker对象移动到新创建的线程中
	  worker->moveToThread(&workerThread);
	  
	  
	  connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
	  connect(this, &Controller::operate, worker, &Worker::doWork);
	  connect(worker, &Worker::resultReady, this, &Controller::handleResults);
	  connect(&workerThread, &QThread::started, worker, &Worker::doWork);
	  workerThread.start();// 开启线程
  }
  ~Controller() {
	  workerThread.quit();// 等待线程结束
	  workerThread.wait();
  }
public slots:
  void handleResults(const QString &);
signals:
  void operate(const QString &);
};

QThread应该被看做是操作系统线程的接口或控制点,而不应该包含需要在新线程中运行的代码。

需要运行的代码应该放到一个QObject的子类中,然后将该子类的对象moveToThread到新线程中。

采用moveToThread的方式,将槽函数所在对象移入子线程,发送信号函数在主线程,槽函数在单独的子线程。

应用场景

适合线程间频繁通信的任务

注意事项

1,自定义类对象不要指定父对象,否则提示:QObject::moveToThread: Cannot move objects with a parent

2,把子线程的finished信号和自定义类对象的deleteLater槽连接,结束子线程则自动析构自定义类的对象。

综上所述

1,常驻任务使用继承QThread重写run,线程逻辑相对独立,不需要与主线程频繁交互。

2,其它的一次性任务或者间歇性任务尽量都用moveToThread,线程执行的任务与 Qt 的事件系统(如信号和槽)交互

允许在不同的线程中运行任务,同时保持与主线程的通信。

你可能感兴趣的:(qt)