Qt5中两种线程操作的方法

Qt5中两种线程操作的方法

##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 virtual run() { 。。。需要运行的代码块。。。 } 
}; 
 
int main(int argc, char** argv) 
{ 
... 
ThreadName thread;
Thread.start();  //通过执行start()函数来启动线程
... 
}
  • 实例:
    threadwork.h
#ifndef THREADWORK_H
#define THREADWORK_H

#include 
#include 

class ThreadWork : public QThread
{
    Q_OBJECT
public:
    ThreadWork(int _index);
    void printMessages();
signals:
    void SendMessage(const QString&);
private:
    int _index;

protected:
    void virtual run();
};

#endif // THREADWORK_H

threadwork.cpp

#include "threadwork.h"
#include 
#include 

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 


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);
}

运行的结果:

Qt5中两种线程操作的方法_第1张图片
这里写图片描述

由结果可以看出确实是有两个线程被开启,并且只有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 
#include 

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 

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中的槽函数,属性都会被加入到新线程中执行 ,而第一种方法中只有run()函数中的在子线程中其他的都在父线程中;
  • 这里的两种方法只针对QThread,Qt中还有一种多线程的操作方法QtconCurrent,这里不作说明;

你可能感兴趣的:(qt5)