Qt多线程之间传递参数

connect(this, SIGNAL(ReceiveThread(void*,int,int)), receiveInfo, SLOT(doReceiveTh(void*,int,int)));
    connect(&receiveThread, SIGNAL(finished()),receiveInfo, SLOT(deleteLater()));

在主线程做以上操作。

上面中ReceiveThread(void*,int,int)是定义的主线程信号,若是要给子线程传递参数就使用emit直接发送信号给子线程。doReceiveTh(void*,int,int)是子线程须要执行的函数。

多线程间须要传递信号给另一个线程的槽,而信号和槽所使用的参数为非QObject,不管其是stl的标准库类型仍是其余类型,都必须先注册,不然信号发送了,槽将会始终不调用。也就是说qt的槽参数必定要是QOject类型的参数(QObject类的子类型也是QObject类型)安全

注册方式如下:

#include <QMetaType>  //该文件为qRegisterMetaType所在头文件,也可使用 #include <QtGui>此头文件包括了全部的qt类型头文件异步

qRegisterMetaType<type>("type");

如我须要传递一个stl的map类型,则需在链接信号和槽以前先注册这个map类型

qRegisterMetaType<std::map<std::string,AppInfo>>("std::map<std::string,AppInfo>");  //AppInfo为自定义的一个类型ui

connect(cfThread,SIGNAL(SetInfo(const map<string,AppInfo>&)),this,SLOT(ShowConfig(const map<string,AppInfo>&));

也能够用如下这种方法,不过此法不安全:

使用connect的第5个参数,将默认的Qt::AutoConnection改成Qt::DirectConnection,也能成功调用槽函数。可是此法不安全。

一般使用的connect,实际上最后一个参数使用的是Qt::AutoConnection类型:

bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method,Qt::ConnectionType type = Qt::AutoConnection )

Qt支持6种链接方式,其中3种最主要的方式如下:

  • Qt::DirectConnection(直连方式)

      当信号发出后,相应的槽函数将当即被调用。emit语句后的代码将在全部槽函数执行完毕后被执行。(信号与槽函数关系相似于函数调用,同步执行)

  • Qt::QueuedConnection(排队方式)

      当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit语句后的代码将在发出信号后当即被执行,无需等待槽函数执行完毕。(此时信号被塞到信号队列里了,信号与槽函数关系相似于消息通讯,异步执行)

  • Qt::AutoConnection(自动方式)

      Qt的默认链接方式,若是信号的发出和接收这个信号的对象同属一个线程,那么工作方式与直连方式相同;不然工作方式与排队方式相同。

即便用排队方式的信号-槽机制,Qt的元对象系统(meta-object system)必须知道信号传递的参数类型。这里手动改成直连方式,Qt的元对象系统就没必要知道参数类型了,因而警告信息消失。但这样作是不安全的,见Qt官方文档:

Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.

总结: 

解决方法有两种:

1、把本身定义的类型注册为元组类型,使用qRegisterMetaType()注册,要把这个函数放在connect()函数使用以前。

参考代码:

#include <QMetaType>//记得包含这个头文件
//my_type是我本身定义的类型
qRegisterMetaType<my_type>("my_type");
connect(xx,SIGNAL(xx(my_type)),xx,SLOT(xx(my_type)));

2、在connect函数的第五个参数加入Qt::DirectConnection

connect(xx,SIGNAL(xx(my_type)),xx,SLOT(xx(my_type)),Qt::DirectConnection);

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工匠Sola

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值