Qt中的多线程使用

Qt提供了许多用于处理线程的类和函数,我们可以在从其中选择一种合适的来实现。总结下来一共有4种:

  1. QThread
  2. QThreadPool and QRunnable

  3. Qt Concurrent

  4. WorkerScript (QML)

下面就通过示例来展示每种方式的使用。示例是参考Qt帮助文档,在Qt5.9.8 MSVC2015下运行,没有考虑线程同步的情况。

一、QThread的使用

QThread是Qt中所有线程控制的基础。每个QThread实例表示并控制一个线程。QThread的使用有2种方式:

  1. 继承QThread,重写run。
  2. QObject::moveToThread。

1.继承QThread,重写run

使用这种方式的时候,QThread实例存在于实例化它的旧线程中,而run()在新线程中执行。这意味着QThread的槽都将在旧线程中执行。如下面代码中的WorkerThread::thread接口,打印的是构造WorkerThread的线程,而run里面打印的新的线程。即使我通过connect接口连接这个槽也是一样的,比如MainWindow中有一个按钮,把按钮的clicked信号的workerThread的thread连接起来。

class WorkerThread : public QThread
{
    Q_OBJECT
public:
    WorkerThread(QObject *parent);
public slots:
    void printThread();
    void stop();
signals:
    void resultReady(const QString &result);

    // QThread interface
protected:
    virtual void run() override;

private:
    bool m_stop;
};

WorkerThread::WorkerThread(QObject *parent)
    : QThread (parent)
    ,  m_stop(false)
{

}

void WorkerThread::printThread()
{
    qDebug() << "Thread1:" << currentThread();
}

void WorkerThread::stop()
{
    m_stop = true;
}

void WorkerThread::run()
{
    qDebug() << "Thread2:" << currentThread();
    while (!m_stop) {
        static int i = 0;
        emit resultReady(QString::number(i++));
        msleep(1000);
    }
}


///////////////////////////////////////////////////////////////////////////
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    WorkerThread *workerThread = new WorkerThread(this);
    connect(workerThread, &WorkerThread::resultReady, this, &MainWindow::handleResults);
    workerThread->start();
    workerThread->thread();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::handleResults(const QString &result)
{
    qDebug() << "result:" << result;
}

2.QObject::moveToThread

在这种方式中,Worker的槽函数中的代码将在一个单独的线程中执行。但是,您可以自由地将Worker的槽函数连接到任何线程中任何对象的任何信号。由于队列连接的机制,跨不同线程连接信号和槽是安全的。在下面的这个示例中,MainWindow::MainWindow中打印的线程和Worker::thread中打印的线程是不一样的。也就是说Worker::thread中的代码是在另外一个线程中执行的。

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);

public slots:
    void thread();
};

Worker::Worker(QObject *parent) : QObject(parent)
{

}

void Worker::thread()
{
    qDebug() << QThread::currentThread();
}


/////////////////////////////////////////////////
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QThread *workerThread = new QThread(this);
    Worker *worker = new Worker;
    worker->moveToThread(workerThread);
    connect(ui->pushButton, &QPushButton::clicked, worker, &Worker::thread);
    connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
    qDebug() << QThread::currentThread();
    workerThread->start();
}

二、QTh

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王哥编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值