首页 > 其他 > 详细

Qt --- 信号槽:第五个参数

时间:2021-05-28 16:59:12      阅读:55      评论:0      收藏:0      [点我收藏+]

 

connect第五个参数说明:

1、Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。

2、Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃。

3、Qt::QueuedConnection:槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个。

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

5、Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接。

 

一。  遇到的问题:在GUI主线程向另一个线程发送信号,槽函数不执行。

 1 static EventLoop* gEventLoop = nullptr;
 2 
 3 void FFF()
 4 {
 5     gEventLoop = new EventLoop();
 6 }
 7 
 8 MainWindow::MainWindow(QWidget *parent) :
 9     QMainWindow(parent),
10     ui(new Ui::MainWindow)
11 {
12     ui->setupUi(this);
13     
14     std::thread ttt(FFF); //另一个线程中创建对象
15     ttt.join();
16     
17     connect(this, &MainWindow::Call, eLoop, &EventLoop::Called, Qt::QueuedConnection); //连接成功 槽函数不执行
18     connect(eLoop, &EventLoop::eee, this, &MainWindow::HHH, Qt::QueuedConnection);
19 
20 }

 

connect(this, &MainWindow::Call, eLoop, &EventLoop::Called, Qt::QueuedConnection); //连接成功 槽函数不执行

这里因为发送信号的对象和接收信号的对象不在同一个线程,使用QueueConnection,但是发送信号后 槽函数不会执行。

 

原因:

信号发送成功后,会把信号放到接收对象所在线程的事件循环队列,排到它的时候,自动调用槽函数。

但是std::thread创建的线程中,没有事件循环,所以没有接收到信号,槽函数不会执行。

 

解决方法:

1.为线程创建一个事件循环。(不会。。。)

2.使用QThread开启线程,QThread自带默认事件循环。

 1 MainWindow::MainWindow(QWidget *parent) :
 2     QMainWindow(parent),
 3     ui(new Ui::MainWindow)
 4 {
 5     ui->setupUi(this);
 6     
 7 //    std::thread ttt(FFF); //另一个线程中创建对象
 8 //    ttt.join();
 9     
10 //    connect(this, &MainWindow::Call, eLoop, &EventLoop::Called, Qt::QueuedConnection); //连接成功 槽函数不执行
11 //    connect(eLoop, &EventLoop::eee, this, &MainWindow::HHH, Qt::QueuedConnection);
12 
13     qThread = new QThread();
14     eLoop = new EventLoop();
15     eLoop->moveToThread(qThread);
16 
17     connect(qThread, &QThread::finished, eLoop, &QObject::deleteLater);
18     connect(qThread, &QThread::finished, qThread, &QObject::deleteLater);
19     connect(qThread, &QThread::destroyed, [=](){qThread = nullptr;});
20     connect(eLoop, &QThread::destroyed, [=](){eLoop = nullptr;});
21     
22     connect(this, &MainWindow::Call, eLoop, &EventLoop::Called, Qt::QueuedConnection);
23     connect(eLoop, &EventLoop::eee, this, &MainWindow::HHH, Qt::QueuedConnection);
24 //    QObject::connect(eLoop, &EventLoop::eee, this, &MainWindow::HHH, Qt::QueuedConnection);
25     qThread->start();
26 }

 

说明:

qThread = new QThread();

eLoop = new EventLoop(); //创建对象

eLoop->moveToThread(qThread); //把对象放到线程中执行,此时线程自带事件循环,发送信号,槽函数能正确调用。(参考 https://www.huaweicloud.com/articles/2a9c964f7ee0900f9bd029224b9f2b26.html


深入理解-》  Qt信号槽机制源码解析







Qt --- 信号槽:第五个参数

原文:https://www.cnblogs.com/linxisuo/p/13448239.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!