一杯清酒邀明月
天下本无事,庸人扰之而烦耳。
posts - 3121,comments - 209,views - 578万

问题:
跨线程使用信号与槽连接,信号的发送时间间隔小于槽函数处理的时间间隔,造成的问题。

子线程下的槽函数,用sleep来模拟槽函数的耗时操作:

1 void MyThread::myTimeout()
2 {
3     qDebug() << "test";
4     QThread::sleep(2);
5 }

主线程下的信号发送函数,通过点击按钮来发送信号:

1 void Widget::on_buttonStart_clicked()
2 {
3     emit startThread();
4 }

线程之间的信号连接函数:

connect(this, &Widget::startThread, myT, &MyThread::myTimeout);

现象:在我们连续点击按钮后,能明显看到打印的信息有延时。

分析:在我们跨线程使用信号与槽时,connect函数默认是使用Qt::QueuedConnection队列的传输方式。当我们的槽函数处理不过来时,会先将传输的信号存入队列中,等槽函数处理完了再拿出来。

解决方法:
我们需要在等槽函数执行完后,才能发送新的信号。

方法一:使用connect的第五个参数,设置为Qt::BlockingQueuedConnection

槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。

connect(this, &Widget::startThread, myT, &MyThread::myTimeout,Qt::BlockingQueuedConnection);

这个也是可以的,但是当我们子线程,处理所需时间很长时,
主线程会出现明显的卡顿,效果不太好。

方法二:
使用bool QObject::blockSignals(bool block)函数屏蔽信号发送,当槽函数处理完后,再开启。

子线程下的改动:

复制代码
1 void MyThread::myTimeout()
2 {
3     qDebug() << "test";
4     QThread::sleep(2);
5     emit recover();
6 }
复制代码

主线程下的改动:

复制代码
 1 void Widget::on_recover()
 2 {
 3     ui->buttonStart->blockSignals(false);
 4 }
 5 
 6 void Widget::on_buttonStart_clicked()
 7 {
 8     emit startThread();
 9     ui->buttonStart->blockSignals(true);
10 }
复制代码

增加信号连接函数:

1 connect(this, &Widget::startThread, myT, &MyThread::myTimeout);
2 connect(myT, &MyThread::recover, this, &Widget::on_recover);

通过增加对信号发送的限制,这样的话可以实现,只有在槽函数处理完成后,才会开始发送信号。

但是用这个函数有一个问题就是,这个对象的所有信号,在屏蔽的期间都不会发送了,也需要等槽函数处理完之后才能发送信号,实验代码如下。

复制代码
 1 void Widget::on_buttonStart_clicked()
 2 {
 3     emit startThread();
 4     ui->buttonStart->blockSignals(true);
 5 }
 6 
 7 void Widget::on_buttonStart_pressed()
 8 {
 9     qDebug() << "信号能正常触发";
10 }
复制代码

所以如果说两个对象之间只是一对一的信号连接的话,可以使用blockSignals函数

1、屏蔽信号的方式还可以用:

复制代码
1 void MyThread::myTimeout()
2 {
3     QObject::sender()->blockSignals(true);
4     QThread::sleep(2);
5     QObject::sender()->blockSignals(false);
6 }
复制代码

这样的话就可以直接在槽函数里,实现将发送信号的对象屏蔽和恢复。

先记录一下,后面有更好的方法再补充。。。

posted on   一杯清酒邀明月  阅读(2000)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示