【Qt】多线程

线程创建

自定义线程类

cpp 复制代码
#ifndef CUSTOMETHREAD_H
#define CUSTOMETHREAD_H

#include <QObject>
#include <QThread>
#include "add.h"

class CustomeThread : public QThread
{
    Q_OBJECT
public:
	// Bind the thread kernel function.
    explicit CustomeThread(Add*& addPtr);

private:
	// Run the thread kernel function
    virtual void run() override;
private:
    Add* m_addFuc {nullptr};
};

#endif // CUSTOMETHREAD_H

主函数

cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Current thread id: " << QThread::currentThreadId();
    //Concrator the thread kernel function object.
    Add* ladd = new Add(); 
    CustomeThread* thread = new CustomeThread(ladd);
    thread->start();
    return a.exec();
}

结果:

shell 复制代码
Current thread id:  0x36d0
current Thread:  0x7f50
100  +  200  =  300

计算的核心函数在子线程中进行。

通过创建一个线程的controller 类,绑定线程执行的kernel函数。然后再子线程的run函数里执行 kernel 函数。

改进

上面的程序中 kernel 函数和 执行线程并没有在同一个线程下,所以虽然Qt通过跨线程调用的机制,在子线程调用成功了,但是终究是一种不安全的方式,所以,为了保险起见,需要将 kernel函数再移入子线程。

cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Current thread id: " << QThread::currentThreadId();
    //Concrator the thread kernel function object.
    Add* ladd = new Add(); 
    CustomeThread* thread = new CustomeThread(ladd);
    ladd->moveToThread(thread);
    thread->start();
    return a.exec();
}

线程循环

事件循环

cpp 复制代码
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    return a.exec();
}

上面的 a.exec() 即让程序进入系统的事件循环,事件循环是一个特殊的死循环,其作用如下:

  • 阻塞程序,使得线程一直执行。
  • 在循环内部可以不断的监听系统发来的信号,并作出反应。
cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QObject>

#include "add.h"
#include "customethread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Current thread id: " << QThread::currentThreadId();
    Add* ladd = new Add();
    CustomeThread* thread = new CustomeThread(ladd);
    ladd->moveToThread(thread);
    thread->start();

    QTimer* timer = new QTimer();
    QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));

    return a.exec();
}

在这个例子里面,使用了一个定时器,向子线程里的 kernel 对象发送信号,出发 add() 槽函数。但是最后并没有触发到。一个原因是: 此时的 ladd 已经在子线程了, 直接连接信号槽,大部分时候只能在信号和槽函数在同一个线程时生效。比如,我们不把 ladd移动到子线程中:

cpp 复制代码
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug() << "Current thread id: " << QThread::currentThreadId();
    Add* ladd = new Add();
    CustomeThread* thread = new CustomeThread(ladd);
    // Not move ladd to subthread!!!!
    //ladd->moveToThread(thread);
    thread->start();

    QTimer* timer = new QTimer();
    QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));

    return a.exec();
}
shell 复制代码
Main thread id:  0x5628
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200

如何子线程的对象发信号?

可以这样连接信号和操

cpp 复制代码
QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()), Qt::QueuedConnection);

向子线程发了信号,子线程就能接受吗?

但是发现即时这样也不能向子线程发信号,这是因为子线程中的run函数并没有调用事件循环,此时子线程已经结束退出了,所以可以在子线程的run函数中增加事件循环

cpp 复制代码
void CustomeThread::run()
{
    exec();
}
shell 复制代码
Main thread id:  0x5384
Current Thread:  0x1638
100  +  100  =  200
Current Thread:  0x1638

自定义事件循环

相关推荐
羑悻的小杀马特11 分钟前
从零搭建群晖私有影音库:NasTool自动化追剧全流程拆解与远程访问协议优化实践
运维·数据库·自动化
TDengine (老段)2 小时前
杨凌美畅用 TDengine 时序数据库,支撑 500 条产线 2 年历史数据追溯
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
葛小白15 小时前
C#数据类型:string简单使用
服务器·数据库·c#
污斑兔5 小时前
MongoDB的$sample是啥?
数据库·mongodb
马丁的代码日记7 小时前
MySQL InnoDB 行锁与死锁排查实战演示
数据库·mysql
拍客圈8 小时前
数据主站+副站做的设置
数据库
计算机学长felix8 小时前
基于SpringBoot的“面向校园的助力跑腿系统”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·后端
fat house cat_8 小时前
【netty】基于主从Reactor多线程模型|如何解决粘包拆包问题|零拷贝
java·服务器·网络·netty
wanhengidc8 小时前
云手机和虚拟机的区别都有哪些?
运维·服务器·安全·智能手机·玩游戏
williamdsy8 小时前
【Docker】[特殊字符] Docker 部署完全指南 - 从本地开发到云服务器
服务器·docker·开发部署流程