通俗易懂玩QT:QThread学习

通俗易懂玩QT:QThread学习

因为公司的业务需求,需要用到线程来解决程序的阻塞问题,特意学习了一下,这里分享给大家。

一、线程介绍(来自百度)

线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。
一条线程实则指进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

二、线程实现(QThread 的使用)

QT 线程的实现有两种方式,一种是直接继承 QThread 类,重写 run() 函数,还有一种是继承 QObject 类,通过 QThread 类方法进行挂载,下面是两种方式的实现步骤:

实现方式一:直接继承 QThread 类,重构 run() 函数

  1. 创建一个类,使其继承 QThread 类:
class TestThread:  public QThread{
    Q_OBJECT
public:
    explicit TestThread(QThread* parent = nullptr);
    ~TestThread();
private:
};
  1. 在类中定义一个 run() 函数:
class TestThread:  public QThread{
    Q_OBJECT
public:
    explicit TestThread(QThread* parent = nullptr);
    ~TestThread();
protected:
    void run();
private:
};
  1. 实现类中的函数以及完成 run() 函数的重构:
TestThread::TestThread(QThread* parent): QThread (parent){
	//需要执行的操作不要放这里
}

TestThread::~TestThread(){}

void TestThread::run(){
	//在这里放需要执行的操作
}
  1. 在 main 函数中初始化线程类:
TestThread* testThread = new TestThread();
  1. 开启线程:
testThread -> start();

到了这里,线程就完成了启动,如果需要关闭线程的话,一共有三种操作,一种是使用 quit() 退出,该操作退出后不执行任何操作,相当于 exit(0);一种是使用 exit(int returnCode = 0) 退出,该操作会间接调用 QEventLoop::exec() 函数,然后返回 returnCode 变量;最后一种是使用信号槽进行关联挂载,当某项操作被执行后,线程直接退出,一般用的比较多的用法connect(this, &QObject::deleteLater, testThread, &QThread::finished);
这是官方提供的案例:

class WorkerThread : public QThread
{
    Q_OBJECT
    void run() override {
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }
signals:
    void resultReady(const QString &s);
};

void MyObject::startWorkInAThread()
{
    WorkerThread *workerThread = new WorkerThread(this);
    connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
    connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
    workerThread->start();
}

实现方式二:继承 QObject 类,通过 QThread 类方法进行挂载

  1. 创建一个类,使其继承 QObject 类:
class TestThread:  public QObject{
    Q_OBJECT
public:
    explicit TestThread(QObject* parent = nullptr);
    ~TestThread();
private:
};
  1. 在类中定义一个插槽来执行操作:
class TestThread:  public QObject{
    Q_OBJECT
public:
    explicit TestThread(QObject* parent = nullptr);
    ~TestThread();
public slots:
	void toDo();
private:
};
  1. 实现类中的插槽以及函数:
TestThread::TestThread(QObject* parent): QObject(parent){
	//需要执行的操作不要放这里
}

TestThread::~TestThread(){}

void TestThread::toDo(){
	//在这里放需要执行的操作
}
  1. 在 main 函数中初始化线程类:
QThread* test = new QThread();
  1. 在 main 函数中初始化对象类:
TestThread* testThread = new TestThread();
  1. 在 main 函数中定义一个函数作为信号来连接卡槽:
void startToDo();
  1. 连接信号槽:
connect(test, &QThread::finished, testThread, &QObject::deleteLater);
connect(this, signal(startToDo()), testThread, &TestThread::toDo);
  1. 将对象挂载到线程上:
testThread -> moveToThread(test);
  1. 开启线程:
test -> start();
  1. 发送信号,通过 connect 函数调用 toDo 卡槽执行相关命令:
emit startToDo();

这是官方提供的案例:

class Worker : public QObject
{
    Q_OBJECT

public slots:
    void doWork(const QString &parameter) {
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }

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

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new 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);
        workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

学习分享,一起成长!接触QT的时间不长,目前差不多快三个月了,有不足之处,欢迎大佬指出来,我会进行更正。有问题可以发送邮件至 [email protected] ,不定时上线查收。

你可能感兴趣的:(QT学习,qt,qt5,thread)