问题描述:
QT程序中通过信号槽函数实现组件间通信。我自己写的信号槽函数,信号函数在read线程,槽函数在主线程。函数的参数类型是uint16_t。通过如下方式连接信号槽,发现信号函数被调用后槽函数无法响应。
connect(this, SIGNAL(SignalFileTransUpdate(uint16_t)), this, SLOT(SlotFileTransUpdate(uint16_t)));
参数类型为uint16_t
连接类型为默认类型
测试结果: 槽函数无响应
问题解决:
方案1: 使用Block连接类型
搜了网上资料,可能是槽函数操作耗时,可以设置连接类型为Qt::BlockingQueuedConnection。设置之后槽函数确实可以响应。
connect(this, SIGNAL(SignalFileTransUpdate(uint16_t)), this, SLOT(SlotFileTransUpdate(uint16_t)), Qt::BlockingQueuedConnection);
参数类型为uint16_t
连接类型为Qt::BlockingQueuedConnection
测试结果: 槽函数响应正常
但是Qt::BlockingQueuedConnection连接类型会导致信号函数所在线程必须等待槽函数执行完才会继续执行,会严重影响执行效率。
方案2:修改函数参数
看到别的说法,可能是信号槽函数所在线程没有在事件循环中。尝试调用别的信号槽函数(参数为int类型),发现调用ok。尝试修改参数类型为unsigned short。修改之后信号槽函数响应ok。
connect(this, SIGNAL(SignalFileTransUpdate(unsigned short)), this, SLOT(SlotFileTransUpdate(unsigned short)));
参数类型为unsigned short
连接类型为默认类型
测试结果: 槽函数响应正常
方案3: 注册uint16_t到QT
使用unsigned short参数ok,使用uint16_t无法响应,所以应该是uint16_t参数类型问题,尝试注册uint16_t到qt,修改之后信号槽函数响应ok。
qRegisterMetaType<uint16_t>("uint16_t");
connect(this, SIGNAL(SignalFileTransUpdate(uint16_t)), this, SLOT(SlotFileTransUpdate(uint16_t)));
注册uint16_t参数类型到QT
参数类型为uint16_t
连接类型为默认类型
测试结果: 槽函数响应正常
疑问:
1. 为什么uint16_t需要注册才能使用,unsigned short可以直接使用?
unsigned short是c++标准数据类型,但是uint16_t是typedefine的类型。相当于自定义的数据类型。
2. 为什么不注册uint16_t,设置Qt::BlockingQueuedConnection连接类型槽函数也可以响应呢?
https://blog.csdn.net/weixin_42981623/article/details/108548379
参考上文,信号槽函数在连接的时候会有几步检查:
1. connect函数的参数检查
2. 获取信号和槽的index
3. 检查信号和槽的参数是否匹配
4. 检查信号参数类型
5. 创建连接对象
在以上检查中,如果连接类型是Qt::BlockingQueuedConnection,不需要检查参数类型。
因为虽然BlockingQueuedConnection是队列连接,但是通过阻塞变成了同步调用,所以不存在参数生命周期问题,所以不会去克隆信号参数,所以也就不需要是QMetaType。