Qt中的多线程(一)

0.前言

Qt中有多种实现多线程的方式,我最常用的有moveToThread()和QtConcurrent::run()两种方式。一般长时间存在的线程我用moveToThread,临时的用QtConcurrent::run(),可惜后者不能使用信号槽。

作为一篇总结,我将列举我了解到的Qt框架中的多线程实现方式。

1.moveToThread()方法配合QThread类

这是Qt官方的推荐实现方式,在QThread的文档中也有其实例代码。

QThread类提供了一个独立于平台的方式来管理线程。一个QThread对象管理程序内的控制的一个线程。线程处理在run()函数中完成。默认情况下,run()通过调用exec()启动事件循环并在线程内运行Qt事件循环。

首先,需要定义一个QObject的子类,实现接口。

#include <QObject>
class ProcessObject :public QObject
{
    Q_OBJECT
public:
    explicit ProcessObject(QWidget *parent = nullptr)
        :QObject(parent){}
    ~ProcessObject()
    {}
signals:
    void someSignal();  
public slots:
    void someSlots(){
        //处理
    }
};

接下来就是创建这个QObject子类及一个QThread对象,并使用moveToThread将QObject子类对象转移到子线程中去执行。

#include <QThread>
#include "ProcessObject.h" //为上面定义的那个类
class ControlObject : public  QObject
{
    Q_OBJECT   
public:
    explicit ControlObject(QWidget *parent = nullptr)
        :QObject(parent){
        process->moveToThread(processThread);
        //利用信号槽让子线程开始工作
        connect(this,&ControlObject::someSignals,process,&ProcessObject::someSlots);
        //返回处理结果
        connect(process,&ProcessObject::someSignals,this,&ControlObject::someSlots);
        //线程结束时释放对象
        connect(processThread,&QThread::finished,process,&QObject::deleteLater);
        //启动线程
        processThread->start();
    }
    ~ControlObject(){
        processThread->quit();
        processThread->wait();
    }
signals:
    void someSignals();
public slots:
    void someSlots(){
        //处理结果
    }
private:
    QThread *processThread=new QThread(this);
    ProcessObject *process=new ProcessObject;
};

引用一段Qt文档中描述:

当线程started()和finished()时,QThread将通过信号通知您,或者您可以使用isFinished()和isRunning()来查询线程的状态。您可以通过调用exit()或quit()来停止该线程。在极端情况下,您可能希望强制terminate()正在执行的线程。但是,这样做是危险和沮丧的。有关详细信息,请阅读terminate()和setTerminationEnabled()的文档。从Qt 4.8开始,通过将finished()信号连接到QObject :: deleteLater(),可以释放生活在刚刚结束的线程中的对象。使用wait()来阻塞调用线程,直到另一个线程完成执行(或直到指定的时间过去)。QThread还提供静态的,独立于平台的睡眠功能:sleep(),msleep()和usleep()分别允许完整的秒,毫秒和微秒分辨率。这些功能在Qt 5.0中公开。一般来说,wait()和sleep()函数是不必要的,因为Qt是一个事件驱动的框架。而不是wait(),考虑监听finished()信号。而不是sleep()函数,请考虑使用QTimer。

start()有一个线程优先级参数,指示操作系统应如何计划新创建的线程,也可用setPriority()设置。删除QThread对象不会停止执行它管理的线程。删除正在运行的QThread将导致程序崩溃。在删除QThread之前等待finished()信号。

还有就时sleep()系列在windows XP下的精度貌似在15ms,这是系统决定的。

(对于释放move到线程的对象,需要关联线程的finished信号,如果在wait()函数后面直接调用deleteLater()的话该对象的析构函数不能正常执行的,如果直接delete的话容易出现异常,所以,记得关联finished信号)

2.使用QtConcurrent::run()方法

使用 QtConcurrent 模块,需要在 .pro 中添加: QT += concurrent,引用文档描述:

该QtConcurrent命名空间提供高层次的API,使人们可以编写多线程程序,而无需使用低级线程原语,如互斥,读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器核心数自动调整使用的线程数。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展。

QtConcurrent::run()可以在另一个线程中运行一个函数:

QFuture<T> QtConcurrent::run(Function function, ...)//参数为函数+参数列表
QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)//也可指定一个QThreadPool线程池,默认为全局的

#include <QtConcurrent>
... ...
method(){
    auto myRun=QtConcurrent::run([=](){
        //处理,此处直接用lambda做参数
    });
    myRun.waitForFinished();//一般我只分离没调用wait
}

使用起来很像std::async,要说有什么不方便的话就是不支持信号槽操作

时间问题,暂时写这两个常用的,下次继续。(如有错误,欢迎指正)

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

龚建波

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

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

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

打赏作者

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

抵扣说明:

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

余额充值