前言
之前从未想过信号槽是可以有返回值的,因为虽然信号发出去了,但是它在事件循环中,什么时候执行还不一定。这个想法固然是对的,但是这也不是不能实现的。
我查了网上的一些资料,发现差不多有一下三种方法:
1.信号槽里加指针或引用。这个不推荐,隐患太多。
2.QMetaObject::invokeMethod 中可传入参数Q_RETURN_ARG来解决。
3.若是不在乎他在哪个线程,当普通函数直接调用也很香。
由于我现在的场景是多线程的,我还是希望该槽函数在该类(槽函数的类)的线程中执行的,所以我最终选择的是QMetaObject::invokeMethod,它是可以选择信号槽的发送方式,而且不需要直接在信号槽里定义指针或者引用,线程安全。
理论
参考文章(写的超级好):Qt之QMetaObject::invokeMethod()使用简介_luoyayun361的博客-CSDN博客_invokemethod qt
其中文章中有一个用法,需要注意下,以后应该可以用到:
注意,要调用的类型必须是信号、槽,以及Qt元对象系统能识别的类型, 如果不是信号和槽,可以使用qRegisterMetaType()来注册数据类型。此外,使用Q_INVOKABLE来声明函数,也可以正确调用。
我的使用示例
由于我的初衷是:获取槽的返回值,然后又可以让槽函数在定义类的线程中调用,所以我最终连接槽函数的方式是:Qt :: BlockingQueuedConnection。要谨慎运用此连接方式,如果同线程就会造成死锁。
void APNetworkComClient::login(const QVariantMap &cert)
{
qlonglong num=-1;
QMetaObject::invokeMethod(m_pHttpClient,"login",Qt::BlockingQueuedConnection,
Q_RETURN_ARG(qlonglong,num),
Q_ARG(QString,cert.value(LOGIN_USERNAME).toString()),
Q_ARG(QString,cert.value(LOGIN_PASSWORD).toString()));
m_httpMsgHndTable.insert(num,&APNetworkComClient::handleHttpLoginResult);
}
结束语
虽然找到解决办法了,但是觉得代码还是写的不够优雅,先凑合吧。