QT 信号槽跨线程 Qt::ConnectionType 的解释和使用(server-socket 高并发数据处理)

信号和槽作为qt独有强大的无缝对象通讯机制模型,  是QT的核心特征。

(一)方法

    static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal ,const QObject *receiver, const QMetaMethod &method Qt::ConnectionType type = Qt::AutoConnection);
    static QMetaObject::Connection connect(const QObject *sender, const char *signal,const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);

(1)信号槽机制:信号槽用于两个对象之间的通信。编程逻辑中我们经常用到任何对象和其他对象进行数据通讯。比如我们做通讯的时候经常遇到数据接收和解析。我们希望数据接收和数据解析用于两个线程工作,提高效率,于是创建两个对象(一个数据接收类,一个数据解析类),这样我们就可通过信号emit(发射)将数据接收对象数据通知到数据解析对象中。函数如下:

connect(data_rev,&myTcpserver::decode_data,data_rev_analyse,&data_analyse::work_start);

(2)这里说一下多个信号和槽的应用过程。一个信号可以关联多个槽函数,多个信号也可以关联同一个槽上。当然也能信号关联到另一个信号上去。那么这里多个槽和信号关联后,当这个信号发射的时候槽会一个接一个的区执行,执行的顺序也是随机的(有网上说是和connect定义顺序有关我认为不准确)。这里无法指定他们的顺序的。

还有一个很重要的,信号槽关联的时候是互不干扰的,他们都占用各自的内存。这一片信号槽执行不会影响其他片信号槽的执行。这里同一线程如果一个槽函数执行进入阻塞不会影响其他槽函数。

(三)这里在说以下信号和槽的声明

声明一个信号要使用signals关键字,在signals前面是不能使用public/private/protected限定符的,因为只有定义该信号的类和子类才可以发射此信号。还有就是这个信号只能声明不能对它进行定义实现,信号没有返回值只能是void 类型。

声明一个槽函数需要用slots关键字,一个槽可以是public/private/protected类型,也可以是虚函数,因为槽函数和普通成员函数是一样的。当然你也可以调用槽函数,和普通成员函数一样的。他和普通成员函数唯一的区别就是他能被信号 关联。

(四)connect 最容易被轻视的一个参数  Qt::ConnectionType

在使用connect 函数时候最容易忽略最后一个参数 Qt::ConnectionType。这里参数表明了关联的方式,默认值是:Qt::AutoConnection。这里我把五个类型都列举以下。

类型描述
AutoConnection
这里如果信号槽在同一个线程这里同DirectConnection;如果信号和槽在不同的线程,这里同QueuedConnection
DirectConnection
发射完信号,槽函数立马执行,只有该槽函数执行完成后,接下来的程序才可以继续执行。
QueuedConnection
这个用到多线程中,在槽函数对象的线程中其他循环结束后执行此函数。发射信号后面代码会立即执行。
BlockingQueuedConnection
这个用到多线程中,在槽函数对象的线程中其他循环结束后执行此函数。发射信号后面代码不会执行指导槽函数结束。
UniqueConnection
同AutoConnection

举例说明:

还是server-socket说明:

为了挂载多个客户端,我们在数据接收线程里面这样的逻辑,每当一个客户端长链接过来我们都使用connect 连接,完成多个客户端数据的接收。如下代码:

connect(tcpSocket,&QTcpSocket::readyRead,this,[=](){tcp_data=tcpSocket->readAll();
emit decode_data(&tcp_data);}

这里数据接收和处理是跨线程的。如果我们还像上面那样定义:

connect(data_rev,&myTcpserver::decode_data,data_rev_analyse,&data_analyse::work_start);就错了,出问题会。因为这里 Qt::ConnectionType类型是AutoConnection的导致问题很多:

(1)tcp_data 是临时变量开辟到栈内存中会被释放,你跨线程就成了野指针

(2)多个客户端同时法数据导致tcp_data被覆盖出错。

所以这里定义成connect(data_rev,&myTcpserver::decode_data,data_rev_analyse,&data_analyse::work_start,QT:BlockingQueuedConnection);

这样等解析槽函数执行完成后在执行emit decode_data(&tcp_data);后面程序没问题了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值