令人不解的问题:

当槽函数是线程类的成员时,为什么依然不在本线程内被调用执行?

隐藏的问题:对象依附于哪一个线程?对象的依附性与槽函数执行的关系?对象的依附性是否可以改变?

对象依附于哪个线程?默认情况下,对象依附于自身被创建的线程例如:对象在主线程(main()函数)中被创建,则依附于主线程

int main(int argc, char* argv[])
{//...TestThread t;     //依附于主线程MyObject m;       //依附于主线程
}

对象的依附性与槽函数执行的关系?默认情况下,槽函数在其所依附的线程中被调用执行

int main(int argc, char* argv[])
{//...TestThread t;     //依附于主线程MyObject m;       //依附于主线程//下面连接中的槽函数都在主线程中被调用执行QObject::connect(&t,SIGNAL(started()),&m,SLOT(getStarted()));QObject::connect(&t,SIGNAL(testSignal()),&m,SLOT(testSlot()));
}

对象的依附性是否可以改变?QObject::moveToThread用于改变对象的线程的依附性,使得对象的槽函数在依附的线程中被调用执行

int main(int argc, char* argv[])
{//...TestThread t;     //依附于主线程MyObject m;       //依附于主线程//改变对象m的线程的依附性,使其依附于线程tm.moveToThread(&t)
}

对象的依附性

MyObject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>class MyObject : public QObject
{Q_OBJECT
public:MyObject();
protected slots:void getStarted();void testSlot();
};#endif // MYOBJECT_H

View Code

TestThread.h

#ifndef TESTTHREAD_H
#define TESTTHREAD_H#include <QThread>class TestThread : public QThread
{Q_OBJECT
protected:void run();
public:TestThread();signals:void testSignal();
protected slots:void testSlot();
};#endif // TESTTHREAD_H

View Code

MyObject.cpp

#include "MyObject.h"
#include <QObject>
#include <QThread>
#include <QDebug>MyObject::MyObject()
{}void MyObject::getStarted()
{qDebug() <<"void MyObject::getStarted()tid = " << QThread::currentThreadId() ;
}void MyObject::testSlot()
{qDebug() << "void MyObject::testSlot() " << QThread::currentThreadId() ;
}

View Code

TestThread.cpp

#include "TestThread.h"
#include <QDebug>TestThread::TestThread()
{connect(this,SIGNAL(testSignal()),this,SLOT(testSlot()));
}void TestThread::run()
{qDebug() << "void TestThread::run() begin...tid = " << currentThreadId();for(int i=0; i<10; i++){qDebug() << "void TestThread::run() i = " << i;sleep(1);}emit testSignal(); //发射的信号谁来接收呢,可以在构造函数中将信号和槽函数进行关联。qDebug() << "void TestThread::run() end...";
}void TestThread::testSlot()
{qDebug() << "void TestThread::testSlot() tid = " << currentThreadId();
}

View Code

main.cpp

#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include "TestThread.h"
#include "MyObject.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "main tid() " << QThread::currentThreadId();TestThread t;MyObject m;QObject::connect(&t,SIGNAL(started()),&m,SLOT(getStarted()));QObject::connect(&t,SIGNAL(testSignal()),&m,SLOT(testSlot()));m.moveToThread(&t);t.start();return a.exec();
}

View Code

课程中使用的是Qt4,MyObject相关的槽函数没有被调用,但是使用Qt5.4,MyObject相关的槽函数被调用了。

下面分析没有被调用的情况:

问题:实验中对象m的槽函数为什么没有全部被执行?

线程中的事件循环信号与槽的机制需要事件循环的支持QThread类中提供的exec()函数用于开启线程的事件循环只有开启事件循环,槽函数才能在信号发送后被调用

信号的发送是随时随地都可以完成的,发送完成后,信号就到事件队列中去了。信号进入事件队列中去有什么用呢?没人理它,它什么用都没有。如何处理事件队列呢?此时事件循环就派上用场了。但凡通过exec开启了事件循环,就会不停的从事件队列中取信号,取到信号后就会去判断该信号有没有关联相关的槽函数,如果有对应的槽函数,则调用相应的槽函数。

想要槽函数在指定的线程中被调用,需要在指定的线程中调用exec函数,开启事件循环。小结论:前提条件对象依附的线程开启了事件循环后置结果对象中的槽函数在依附的线程中被调用执行

只需要在TestThread.cpp的run函数中加上exec函数即可

void TestThread::run()
{qDebug() << "void TestThread::run() begin...tid = " << currentThreadId();for(int i=0; i<10; i++){qDebug() << "void TestThread::run() i = " << i;sleep(1);}emit testSignal(); //发射的信号谁来接收呢,可以在构造函数中将信号和槽函数进行关联。exec();qDebug() << "void TestThread::run() end...";
}

View Code

从打印结果看,与上面没有使用exec的执行结果并无不同,很可能是因为版本不同造成的。

从打印结果看,MyObject的两个槽函数都被调用了,且是在依附于t的那个线程。但是t的槽函数还是依附于主线程,我也想让t的槽函数依附t,怎么操作?非常简单,只需要在main.cpp中的main函数中,加入t.moveToThread(&t)即可,如下所示:

int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "main tid() " << QThread::currentThreadId();TestThread t;MyObject m;QObject::connect(&t,SIGNAL(started()),&m,SLOT(getStarted()));QObject::connect(&t,SIGNAL(testSignal()),&m,SLOT(testSlot()));m.moveToThread(&t);t.moveToThread(&t);t.start();return a.exec();
}

View Code

研究槽函数的具体执行线程有什么意义?当信号的发送与对应槽函数的执行在不同线程中,可能产生临界资源的竞争问题

比如说,在run函数对某一个临界资源进行修改,在槽函数中也对临界资源进行修改,槽函数的调用是在另一个线程中完成的,此时调用槽函数的线程和本身的线程就可能产生竞争问题。

多线程中的信号与槽(中)相关推荐

  1. Qt多线程中的信号与槽

    文章目录 1 多线程中的信号与槽 2 对象的依附性 2.1 对象的依附性 2.2 开启线程事件循环 2.3 线程事件循环的结束 2.4 设计实例 3 信号与槽的连接方式 3.1 Qt::DirectC ...

  2. Qt 多线程中地信号与槽

    Qt 多线程中地信号与槽 函数原型: 1 QObject::connect(const QObject *sender, const char *signal, const QObject *rece ...

  3. Qt静态函数中的信号和槽问题

    目录 介绍 Qt中的信号和槽 一般形式 当发送信号的地方为静态函数时 存在问题 解决方案 介绍 信号和插槽用于对象之间的通信.信号和插槽机制是Qt的一个核心特性,可能是与其他框架提供的特性最为不同的部 ...

  4. Qt编程中的信号和槽机制

    Qt编程中的信号和槽机制 在使用自定义类创建一个按钮之后,只能看到一个按钮的图形,但是使用鼠标点击并无任何反应,下面想要实现一个"点击按钮可以关闭窗口"的功能. 关闭窗口的功能可以 ...

  5. Qt中的信号与槽机制解析

    注:要想使用Qt的核心机制信号与槽,就必须在类的私有数据区声明Q_OBJECT宏,然后会有moc编译器负责读取这个宏进行代码转化,从而使Qt这个特有的机制得到使用. 所谓信号槽,简单来说,就像是插销一 ...

  6. Qt多线程使用 和 信号与槽传参 需要注意的问题

    Qt中提供了线程类,默认窗口是主线程,这个时候如果我们的业务逻辑很费时,就会一直使用主线程,页面可能会卡顿甚至崩溃.那么将业务逻辑放入子线程,能够避免页面的卡顿,保证操作是流畅的,还能提高程序的执行效 ...

  7. python qt designer 重定向_[Python自学] PyQT5-QTDesigner中关联信号和槽

    一.什么是信号什么是槽 信号和槽是QT的核心机制. 1.信号 信号,是由对象或空间发出去的消息.例如单击按钮控件. 信号可以理解为触发的事件. 2.槽 发送出去的信号需要有一段代码来拦截,并执行一些操 ...

  8. matlab有信号与槽机制么,笔记:Qt5中的信号与槽,不要再用SIGNAL,SLOT了

    看的书是Qt5.9,但书上却用的Qt4中的通用用法:SIGNAL和SLOT宏, 不过,书后面却又给了一种传递信号和槽函数地址的用法(Qt5的用法),但是这本书的作者在这块却说的不好,如下图: 首先要知 ...

  9. Qt中解决信号和槽不能使用自定义结构体的问题

    在Qt中信号和槽使用自定义的结构时,运行的时候发现报错不能识别结构体 解决办法: 一定要将自定义结构体定义为typedef struct 使用Q_DECLARE_METATYPE(结构体名),将结构体 ...

最新文章

  1. CVPR 2020 | 基于多智能体RL实现多轮连续交互,IteR-MRL使图像分割算法达到医用标准...
  2. 程序员算事业单位吗_清北毕业出来的程序员不如三本公务员?网友:你开心就好...
  3. Qt中槽函数触发两次的两种场景分析
  4. Java程序员需要掌握哪些技能才能通过大公司的面试
  5. c# url编码 字母编码_我如何通过每天30分钟编码来完成#100DaysOfCode挑战
  6. DWZ中navTab使用解析
  7. ES6学习笔记(三):教你用js面向对象思维来实现 tab栏增删改查功能
  8. Jmeter系列之参数化
  9. 手机号归属地 mysql脚本_示例演示手机号归属地查询功能
  10. 英魂之刃服务器维护中修改,英魂之刃gg修改教程 | 手游网游页游攻略大全
  11. android 加载系统私有库,Android 搭建私有maven仓库及上传项目
  12. angular toastr插件
  13. 用wget命令整站下载
  14. 大型分布式网站架构如何设计
  15. Java具有哪些语言特点
  16. stm32用什么软件编辑呢
  17. Mac Book系统时间校准
  18. nacos和eruka的区别
  19. 距总决赛还有100天!详解沃顿KWHS全球投资挑战赛
  20. vcpkg+opencv4(sfm+vtk)+openMVS+SFM算法-github代下载(http://gitd.cc/)

热门文章

  1. 新版标准日本语初级_第七课
  2. 漫谈核心能力(1) -- 不学则无知
  3. 如何配置Git环境变量
  4. php uniqid 高并发,PHP uniqid 高并发生成不重复唯一ID
  5. Prettier格式化配置
  6. 注意力机制:基于Yolov5/Yolov7的Triplet注意力模块,即插即用,效果优于cbam、se,涨点明显
  7. vivo-悟空活动H5 活动加载优化
  8. 在设计师眼中,国产手机是怎样的?
  9. 计算机毕业设计Node.js+Express银行理财推荐系统(源码+程序+lw+远程调试)
  10. 区块链技术在金融领域的应用