qt-QThread的使用

QThread简介:

Qt中的QThread类提供了与平台无关的线程。一个QThread代表了一个应用程序中可以独立控制的线程,它与进程中的其他线程分享数据,但是是独立执行的。相对于一般的程序都从main()函数开始执行,QThread从run()函数开始执行。默认的,run()通过调用exec()来开启事件循环,并在线程内运行一个Qt事件循环。

创建线程的两种方式
  1. 要创建一个线程,需要子类化QThread,并且重写run()函数,这种用法比较简单,而且不是很常用,就不赘述了。
  2. 第二种方式是使用QObject::moveToThread函数。例如:
//Worker.h ->执行耗时操作的类
#include <QObject>

//线程类
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);
public slots:
    void doWork();
    void doStop();

signals:
//    void startWork();

private:
    volatile bool stopped; //volatile关键字保证stopped的值一直是最新的,防止多线程访问的时候出现错误
};

//Worker.cpp
#include "worker.h"
#include <QDebug>
#include <QThread>
Worker::Worker(QObject *parent)
    : QObject{parent}
{
   stopped = false;
}

void Worker::doWork()
{
    while(!stopped){
//        for(int i = 0;i<1000;i++){
//            qDebug() << QString("in work : %1").arg(i);
//        }
        QThread::sleep(1);
        qDebug() << QString("working");
    }
    stopped = false;
}

void Worker::doStop()
{
    qDebug() << "准备结束线程!!!";
    stopped = true;
}

//Widget.h
#include <QWidget>
#include <QThread>
#include "worker.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_start_clicked();

    void on_stop_clicked();

private:
    Ui::Widget *ui;
    QThread* workerThread; //工作线程
    Worker* worker; //工作类

signals:
    void startThread();
    void stopThread();
};

//Widget.cpp
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->start->setEnabled(true);
    ui->stop->setEnabled(false);
    workerThread = new QThread;
    worker = new Worker;
    worker->moveToThread(workerThread);//开启一个新的线程(将Worker移入到这个线程,执行耗时的任务)
   connect(workerThread,&QThread::finished,worker,&Worker::deleteLater); //线程结束时,释放工作类
    connect(this,&Widget::startThread,worker,&Worker::doWork);
    connect(this,&Widget::stopThread,[=](){
        worker->doStop();
    });
    workerThread->start();
}

Widget::~Widget()
{
    workerThread->quit();
    workerThread->wait();
    delete ui;
}


void Widget::on_start_clicked()
{
    emit startThread();
    ui->start->setEnabled(false);
    ui->stop->setEnabled(true);
}


void Widget::on_stop_clicked()
{
    ui->start->setEnabled(true);
    ui->stop->setEnabled(false);
    emit stopThread();
}

演示效果:
在这里插入图片描述
总结: 这样,Worker的doWork()槽中的代码就可以在单独的线程中执行,使用这种方法可以很容易地将一些费时的操作放到单独的工作线程中来完成。可以将任意线程中任意对象的任意一个信号关联到Worker的槽上,不同线程间的信号和槽进行关联是安全的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Qt 中使用 QThread 实现多线程可以分为以下步骤: 1. 创建一个继承自 QThread 的子类,重写其 run() 方法,该方法将在新的线程中执行。 2. 在子类中定义信号和槽,以便在主线程和子线程之间进行通信。 3. 在主线程中创建子线程对象,并使用 start() 方法启动线程。 4. 在主线程中使用 connect() 方法将子线程的信号与主线程的槽连接起来,以实现跨线程通信。 以下是一个简单的示例: ```c++ #include <QThread> #include <QDebug> class MyThread : public QThread { Q_OBJECT signals: void mySignal(QString message); protected: void run() override { qDebug() << "Thread started"; emit mySignal("Hello from thread"); qDebug() << "Thread finished"; } }; class MyClass : public QObject { Q_OBJECT public slots: void mySlot(QString message) { qDebug() << "Received message:" << message; } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MyThread thread; MyClass obj; QObject::connect(&thread, &MyThread::mySignal, &obj, &MyClass::mySlot); thread.start(); return a.exec(); } #include "main.moc" ``` 在这个例子中,我们定义了一个 MyThread 类,它继承自 QThread,重写了 run() 方法,并定义了一个 mySignal 信号。我们还定义了一个 MyClass 类,它有一个名为 mySlot 的槽,用于接收 MyThread 发出的信号。在 main() 函数中,我们创建了一个 MyThread 对象和一个 MyClass 对象,并使用 connect() 方法将 mySignal 信号连接到 mySlot 槽。然后,我们调用 start() 方法来启动线程。当 run() 方法被执行时,它将发出 mySignal 信号,并传递一个字符串参数。这个信号将被发送到主线程,并调用 mySlot 槽来处理它。最后,我们调用 a.exec() 来启动 Qt 的事件循环,以便在主线程中接收信号和执行槽函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值