当前位置: 首页 > news >正文

【Qt中信号槽连接connect有接收者和无接收者的区别】

Qt中信号槽连接connect有接收者和无接收者的区别

    • 概述
    • 代码验证
    • 结论

概述

在qt开发过程中,在多线程的环境下,发现程序有些问题,根据程序打印出来的提示,发现与线程有关。最终定位到connect函数处,于是有以下的研究:关于connect函数有接收者和无接收者的区别。

代码验证

验证工程代码文件包括:define.h(类的定义) mainwindow类文件。
根据打印结果(可以看mainwindow.cpp的注释),可以得出结论(也在注释里面)
注意:尽量使用有接收者的connect函数,同时,信号方的线程指的是发送信号的线程,而不是信号拥有者的线程。
define.h:

#ifndef DEFINE_H
#define DEFINE_H
#include<QDebug>
#include<QDateTime>
#pragma execution_character_set("utf-8") //如果源文件是UTF-8+无BOM的编码方式,则一定不能加#pragma execution_character_set(“utf-8”)
#define myDebug qDebug()<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")<<__FILE__<<__LINE__
#include<QThread>
class Worker: public QObject
{Q_OBJECT
public:Worker(QObject* parent = nullptr): QObject(parent) {}signals:void finished();public slots:void work(){myDebug << "工作完成 worker";myDebug << QThread::currentThread() << " ==" << sender()->thread() << "==" << this->thread() << this->metaObject()->className();emit finished();}
};class Worker2: public QObject
{Q_OBJECT
public:Worker2(QObject*parent = nullptr): QObject(parent){}void emitAfterWork(){emit afterWork();}
signals:void afterWork();
public slots:void finishedSlots(){myDebug << "工作完成,下班,Work2";myDebug << QThread::currentThread() << " ==" << sender()->thread() << "==" << this->thread() << this->metaObject()->className();emit afterWork();}
public:};
#endif // DEFINE_H

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include"define.h"
QT_BEGIN_NAMESPACE
namespace Ui
{class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow* ui;Worker* wk;Worker2* wk2;
};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);myDebug;wk2 = new Worker2;wk = new Worker;QThread *thread = new QThread;wk->moveToThread(thread);thread->start();connect(ui->pushButton, &QPushButton::released, wk, &Worker::work);//按钮会触发Worker类的finished信号,且是在Worker所在线程的。//wk与当前类对象不在同一线程:wk在子线程,而当前类对象在主线程。//无接收者的connect,槽函数的执行线程是由信号端决定的,打印结果:QThread(0x6c80c8)  == QThread(0x6c80c8) == QThread(0x6c5f50) MainWindow//结果表明,在没有接收者的情况下,槽函数所在线程就是信号端的线程(至于是发送者的线程  还是  执行发送信号的线程要从下面另一个connect确定)//有接收者的connect,槽函数与接收者在同一个线程,打印结果:QThread(0x13ed680)  == QThread(0x13f8748) == QThread(0x13ed680) MainWindow//结果表明,在接收者的情况下,槽函数所在线程就是接收者的线程connect(wk, &Worker::finished, /*this,*/ [ = ](){myDebug << "工作完成,下班,Work2";myDebug << QThread::currentThread() << " ==" << wk->thread() << "==" << this->thread() << this->metaObject()->className();wk2->emitAfterWork();});//此处connect用于判断发送端的线程是:发送者的线程 还是 发送信号的线程//由于wk2与当前类都在主线程里面,而“上面的connect使用无接收者的connect函数,则信号会在子线程发出”//如果发送端的线程是指wk2所在的线程,那么下面connect无论是有接收者还是没有,那打印出来的线程应该都是一样的。//如果不一样,则说明线程由发送信号的线程决定而不是发送者所在的线程//无接收者connect打印结果:QThread(0x767720)  == QThread(0x7657d8) == QThread(0x7657d8) MainWindow//结果表明:在没有接收者的情况下,槽函数所在线程是由信号端确定的,但这里线程又不是发送者所在的线程,那么就是槽函数的线程就是由发送信号的线程所确定//有接收者connect打印结果:QThread(0x1316550)  == QThread(0x1316550) == QThread(0x1316550) MainWindow//总结,无论什么情况都应该尽量使用有接收者的connect,而无接收者的connect 大致等价与 有接收者的connect的第五个参数为Qt::DirectConnection。//即槽函数在发送信号的线程中执行,这样是不安全的。connect(wk2, &Worker2::afterWork, this, [ = ](){myDebug << "收到下班信号,mainwindow";myDebug << QThread::currentThread() << " ==" << wk2->thread() << "==" << this->thread() << this->metaObject()->className();});}MainWindow::~MainWindow()
{delete ui;
}

结论

总结,无论什么情况都应该尽量使用有接收者的connect,而无接收者的connect 大致等价与 有接收者的connect的第五个参数为Qt::DirectConnection。 即槽函数在发送信号的线程中执行,这样是不安全的。

http://www.dtcms.com/a/365932.html

相关文章:

  • LeetCode 20.有效的符号算法解析及栈的相关知识
  • FTL文件格式的原理与应用(AI)
  • 【工具变量】上市公司绿色供应链管理示范企业DID数据(2010-2024年)
  • AUTOSAR进阶图解==>AUTOSAR_TPS_ARXMLSerializationRules
  • Linux学习-硬件
  • 2025年IT行业入门级证书选择与分析
  • 从竞态到原子:pread/pwrite 如何重塑高效文件 I/O?
  • 深入浅出:YOLOv8性能评估指标与电科金仓2025AI新成果
  • SuperMap GIS基础产品FAQ集锦(20250819)
  • C++----模板特化以及模板声明与定义分离问题
  • 2025 大学生必考 IT 行业证书
  • BigemapPro中的坐标定位于与拾取
  • NuttX编译流程与config.h生成解析
  • STM32G4 电流环闭环
  • Springboot3+SpringSecurity6Oauth2+vue3前后端分离认证授权-授权服务
  • 后端框架(SpringBoot):自动配置的底层执行流程
  • 2025年经管专业人士证书选择与分析
  • 深入理解Cloudflare错误1006、1007和1008:原因、解决方案和预防措施
  • Android创建demo脚本
  • 比亚迪欧洲逆袭特斯拉,新能源出海新纪录!
  • Redis 哨兵模式(Sentinel Mode)
  • Reflection反射
  • rsync + lsyncd 的高效文件实时同步系统
  • Docker Pull 代理配置方法
  • 投影矩阵:计算机图形学中的三维到二维转换
  • GDAL 下载安装
  • 【深度学习新浪潮】用3DGS做三维重建有哪些主要的技术路线可供选择?
  • 论文介绍:“DUSt3R”,让 3D 视觉从“繁琐”走向“直观”
  • Redis初阶学习
  • 今日行情明日机会——20250903