扣扣技术交流群:460189483
1. 通过创建QTread子实现run()函数来实现
-
QThread::run()是线程的入口 相当于 main函数一样 创建的线程通过调用start()来执行run(); run() 是一个虚函数 通过子类实现方法
-
大概的框架:
-
class ThreadName:public QThread { Q_OBJECT public: ThreadName(QObject* parent=0):QThread(parent){} public slots: signals: protected: void run() { 。。。需要运行的代码块。。。 } }; int main(int argc, char** argv) { ... ThreadName thread; Thread.start(); //通过执行start()函数来启动线程 ... }
- 实例:
threadwork.h -
#ifndef THREADWORK_H #define THREADWORK_H #include <QThread> #include <QDebug> class ThreadWork : public QThread { Q_OBJECT public: ThreadWork(int _index); void printMessages(); signals: void SendMessage(const QString&); private: int _index; protected: void run(); }; #endif // THREADWORK_H
threadwork.cpp
-
#include "threadwork.h" #include <mainwindow.h> #include <QDebug> ThreadWork::ThreadWork(int _index) { this->_index=_index; } void ThreadWork::printMessages() { qDebug()<<"printMessage线程id:"<<QString::number((int)QThread::currentThreadId()); } void ThreadWork::run() { qDebug()<<"run()线程id:"<<QString::number((int)QThread::currentThreadId()); int k =0; while(true) { const QString s = "我是线程:"+QString::number(_index); sleep(1); emit SendMessage(s); if(k==10) { this->terminate(); this->wait(); } k++; } }
Mainwindow.cpp
-
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); qDebug()<<"主线程id:"<<QString::number((int)QThread::currentThreadId()); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_start_clicked() { ThreadWork *tw = new ThreadWork(_current); connect(tw,SIGNAL(SendMessage(const QString&)),this,SLOT(ShowMessages(const QString&))); tw->printMessages(); tw->start(); _current++; } void MainWindow::ShowMessages(const QString& SMessages) { messagesLists+=SMessages; QStringListModel * _mode = new QStringListModel(messagesLists); this->ui->listView->setModel(_mode); }
运行的结果:
-
由结果可以看出确实是有两个线程被开启,并且只有run()中的部分在新开启的线程中,其他在创建Qthread这个类对象的线程中,这里是在主线程中;注意:信号和槽 是跨线程的 即实现了线程之间的通信;
2. 通过moveToThread()函数来实现
作用:将某一个对象从当前的线程中推到另一个线程中,但是不能将其他线程的对象拉到当前线程上;
原理:其实是通过信号和槽的方式实现;将需要通过线程处理的代码放入到一个槽函数中;
注意:如果对象存在父对象 则moveToThread()函数不起作用,在帮助文档中的原话是:
Changes the thread affinity for this object and its children. The object cannot be moved if it has a parent. Event processing will continue in the targetThread.大概框架:
Class doWork : public QObject { Q_OBJECT public: explicit DoWork(QObject *parent = 0); void qutamde(); signals: public slots: void qunimade(); } Int main() { doWork *dw = new doWork() ; //实例化类对象 QThread *t = new QThread(); //实例QThread对象 Dw->moveToThread(t); //将槽函数中需要执行的代码放入新创建的线程中执行 Connect(对象,SIGNAL(对象信号),dw,SLOT(槽函数)); //连接信号和槽 }
- 实例:
dowork.h -
#ifndef DOWORK_H #define DOWORK_H #include <QObject> #include <QThread> class DoWork : public QObject { Q_OBJECT public: explicit DoWork(QObject *parent = 0); void qutamde(); signals: void nihao(); public slots: void qunimade(); void nihaoma(); }; #endif // DOWORK_H
dowork.cpp
-
#include "dowork.h" #include "QDebug" DoWork::DoWork(QObject *parent) : QObject(parent) { } void DoWork::qutamde() { qDebug()<<"非槽函数 "<<"我的线程id:"+QString::number((int)QThread::currentThreadId()); } void DoWork::qunimade() { qDebug()<<"槽函数 "<<"我的线程id:"+QString::number((int)QThread::currentThreadId()); } void DoWork::nihaoma() { qDebug()<<"你好吗 "<<"我的线程id:"+QString::number((int)QThread::currentThreadId()); }
Mainwindows.cpp
-
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); t = new QThread(); dw = new DoWork(); dw->moveToThread(t); connect(t,SIGNAL(started()),dw,SLOT(qunimade())); connect(ui->pushButton,SIGNAL(clicked()),dw,SLOT(nihaoma())); qDebug()<<"主线程线程id:"<<QString::number((int)QThread::currentThreadId()); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { dw->nihao(); t->start(); dw->qutamde(); } void MainWindow::on_pushButton_2_clicked() { t->terminate(); //不建议使用这种方法 t->wait(); /// qDebug()<<"线程结束"; }
-
可以看出dowork对象中的所有的槽函数都在新的线程中执行,而非槽函数则在创建线程的线程中执行,这里是主线程;
我们来验证:The object cannot be moved if it has a parent. 这句话
我们将
dw = new DoWork(); 改为dw = new DoWork(this); 添加一个父对象;
- 执行结果: -
结果显示并没有存在新的线程;
注意:Dw->moveToThread(t); Dw中的槽函数都会被加入到新线程中执行