一、以前就发现过这个问题:
在Qt项目中,有时候为了让自己的类,可以重载操作符 '=','<<','>>'. 也有时候需要用一个类进行文件的读写,所以很多C++类还是要简单化的,不需要继承QObject,不需要Qt的元对象机制。
但是对于这些简单C++类,有些时候要是调用Qt的信号槽当做参数进行跨线程发送,就会出现如下问题:
这种情况一般,编译可以通过,但会出现如下提示。
QOBject::connect:Cannot queue arguments of type 'MoSystemLog'
(Make sure 'MoSystemLog' is registed using qRegisterMetaType().)
意思是说,信号槽队列中的数据类型必须是系统能识别的元类型,不然得用qRegisterMetaType()进行注册。
二、解决方法:
第一种注册法:qRegisterMetatType<MoSystemLog>("MoSystemLog")
第二种修改Connect,加一个属性Qt::directConnection.
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);
三、方法解释:
1、第一种解决方法,即使用排队方式的信号-槽机制,Qt的元对象系统(meta-object system)必须知道信号传递的参数类型。这样元系统可以将信号参数COPY下来,放在队列中等待事件唤醒,供槽函数调用。Just a note here, if you would have to pass custom data types between threads in Qt. As we know, a signal-slot connection is then (by default) of type Qt::QueuedConnection. Because in such a situation Qt needs to store passed parameters for a while, it creates their temporary copies. If it doesn’t recognize the passed data type, throws out an error:
2、第二种方法,直接调用对方槽函数,不需要保存参数。但是官方认为这样做有风险。
四、背景知识:
1、首先要了解enum Qt::ConnectionType
Qt支持6种连接方式,其中3种最主要:
Qt::DirectConnection(直连方式)
当信号发出后,相应的槽函数将立即被调用。emit语句后的代码将在所有槽函数执行完毕后被执行。(信号与槽函数关系类似于函数调用,同步执行)
Qt::QueuedConnection(排队方式)
当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕。(此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信,异步执行)
Qt::AutoConnection(自动方式)
Qt的默认连接方式,如果信号的发出和接收这个信号的对象同属一个线程,那个工作方式与直连方式相同;否则工作方式与排队方式相同。
Qt官方文档中写明:
With queued connections, the parameters must be of types that are known to Qt's meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes. If you try to use a queued connection and get the error message
QObject::connect: Cannot queue arguments of type 'MyType'
callqRegisterMetaType() to register the data type before you establish the connection.
注意上面紫色的内容。
connect的第五个参数用于指定反应速度:
若将:
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
this,SLOT(sendRes(QUuid,QByteArray,bool)));
改为:
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)),
this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);
可解决因信号没有及时发送,致使connect的接收方的槽不能作进一步处理,但是有风险
参考文章:
1、http://blog.ayoy.net/2009/2/15/registering-custom-types
2、http://dev.wo.com.cn/bbs/redirect.jsp?fid=25127&tid=150302&goto=nextoldset
3、http://blog.csdn.net/s04023083/article/details/4746544
- 大小: 26.7 KB
分享到:
相关推荐
QT 利用继承Qobject实现多线程 利用moveToThread()函数将所需在新线程中处理的内容转移到开辟的新线程中 此外还利用了对不同线程进行加锁
Qt Creator 多线程读取文件到程序显示 利用QT Creator多任务读取一个文档到程序里 为了防止直接读取文件里的内容太大而发生卡顿,于是多线程读取将更高效的解决这个问题。 效果图如下: 其中pro文件无需改动,...
Qt 多线程采用继承QObject方式编写、
qtThread_2.rar qt 线程练习样例代码,继承Qobject方式
在次线程中输出系统时间,传递参数到str_time中,发出信号在主界面lineedit里显示系统时间
Qt诺基亚官方中文教程L2_Qt的对象模型和信号槽概念,QObject类,元数据,内省,属性,内存管理
采用Qt5.9和VS2015的环境,编写了一个多线程的小程序,线程的创建方式继承QObject。
本示例程序使用Qt Creator创建多线程示例,下载下来可直接编译运行: 1.继承QObject 2.继承QThread 3.继承QObject魔改 教程地址: https://tangxing.blog.csdn.net/article/details/111615381
以文件复制为例将继承QThread、QObject,两种Qt多线程方式作简单对比
qt多线程使用,推荐用法,继承QObject,使用worktothread方法。
QT_CTP_MD接口的例子,包括了初始化,登录,订阅,还有非QOBJECT类和主UI之间的通信方法
被绑定到某个Qthread上的Qobject对象,其信号-槽事件循环由该线程负责。这样,便可方便的指定某个套接字对象使用的线程。同样,受惠于Qt的良好封装,直接支持Tcp套接字及SSL套接字,且在运行时可动态调整。(注:...
一个不带QObject依赖的Qt信号系统的纯Python实现
你不需要手动声明信号和槽,而是使用Qt提供的默认信号和槽来进行连接。默认信号和槽的机制在Qt的部分组件中内置,例如`QPushButton`的点击事件等。 + **使用说明:** 1. **默认信号和槽的连接:** - 对于某些Qt...
创建线程有两种办法,一种继承QThread重载run, 一种继承QObject用moveToThread,详细代码比较
16. 深入 Qt5 信号槽新语法 17. 文件对话框 18. 事件 19. 事件的接受与忽略 20. event() 21. 事件过滤器 22. 事件总结 23. 自定义事件 24. Qt 绘制系统简介 25. 画刷和画笔 26. 反走样 27. 渐变 28. 坐标系统 29. ...
Qt为C++语言增加的特性就是在Qt Core模块里实现的,这些扩展特性由Qt的元对象系统实现,包括信号与槽机制、属性系统、动态类型转换等。 1.2.元对象系统 Qt的元对象系统(Meta-Object-System)提供了对象之间通信的...
Qt为C++语言增加的特性就是在Qt Core模块里实现的,这些扩展特性由Qt的元对象系统实现,包括信号与槽机制、属性系统、动态类型转换等。 1.2.元对象系统 Qt的元对象系统(Meta-Object-System)提供了对象之间通信的...
qt 6.2.2+msvc 2019。qt安装的objectcontroller工具非常好用,但objectcontroller只支持qobject类型数据。这里做了修改,增加了对gadget型数据的支持。
简述了QObject的源代码,对初学者也能看懂