【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

自定义事件循环

相关推荐
m0_699659561 小时前
QT知识点复习
开发语言·qt
黑牛先生1 小时前
【Linux】动静态库
linux·运维·服务器
vcshcn2 小时前
DBASE DBF数据库文件解析
数据库·dbase
AIGC大时代3 小时前
对比DeepSeek、ChatGPT和Kimi的学术写作撰写引言能力
数据库·论文阅读·人工智能·chatgpt·数据分析·prompt
如风暖阳3 小时前
Redis背景介绍
数据库·redis·缓存
深蓝海拓3 小时前
基于深度学习的视觉检测小项目(十六) 用户管理界面的组态
人工智能·python·深度学习·qt·pyqt
lingllllove4 小时前
Redis脑裂问题详解及解决方案
数据库·redis·缓存
字节全栈_BjO5 小时前
mysql死锁排查_mysql 死锁问题排查
android·数据库·mysql
微光守望者5 小时前
Redis常见命令
数据库·redis·缓存
martian6656 小时前
第六篇:事务与并发控制
数据库