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官方文档:
总结:
解决方法有两种:
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);