首页 > 其他分享 >Qt - 信号与槽的第五个参数

Qt - 信号与槽的第五个参数

时间:2024-11-12 11:57:19浏览次数:1  
标签:Qt parent mainwindow 参数 线程 第五个 include MainWindow

connent函数第五个参数的作用

connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

第五个参数代表槽函数在哪个线程中执行 :

自动连接(Qt::AutoConnection),默认的连接方式,如果信号与槽,也就是发送者与接受者在同一线程,等同于直接连接;如果发送者与接收者处在不同线程,等同于队列连接

  • 在你的具体情况下,如果子线程发射信号,并且该信号的接收者是主线程中的一个对象,同时主线程运行着事件循环,那么槽函数将在主线程中执行

直接连接(Qt::DirectConnection - 同步),当信号发射时,槽函数立即直接调用。无论槽函数所属对象在哪个线程,槽函数总在发送者所在线程执行,即槽函数和信号发送者在同一线程

  • 如果信号发射者和槽接收者位于不同的线程中,并且你使用了 Qt::DirectConnection,那么就会违反 Qt 的线程安全规则,因为直接调用可能会在不同线程之间造成竞争条件或数据损坏。

队列连接(Qt::QueuedConnection - 异步),当Thread1触发信号后,信号会在处理完前面的任务后再调用相应的槽函数,槽函数在接收者线程中执行,Thread1立即会执行下面任务,无需等待接收者线程执行槽函数完毕。

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

 


自动连接(Qt::AutoConnection)

  • 自动连接(Qt::AutoConnection),默认的连接方式,如果信号与槽,也就是发送者与接受者在同一线程,等同于直接连接;如果发送者与接收者处在不同线程,等同于队列连接

 


直接连接(Qt::DirectConnection - 同步)

同线程

mainwindow.cpp(主线程)

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(this,SIGNAL(sig()),this,SLOT(slot()),Qt::DirectConnection);

    emit sig();

    for(int i=0; i<10;i++)
    {
        qDebug() << i;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slot()
{
    qDebug()<<"执行槽函数";
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "thread1.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;    

private slots:
    void slot();
signals:
    void sig();
};

#endif // MAINWINDOW_H

结论:发射信号后立马执行槽函数。

 

不同线程

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qDebug()<<u8"主线程ID"<<QThread::currentThreadId();

    connect(&m_thread1,SIGNAL(sigThread1()),this,SLOT(slot()),Qt::DirectConnection);

    m_thread1.start();
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::slot()
{
    qDebug()<<u8"执行槽函数---线程ID"<<QThread::currentThreadId();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <thread1.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    Thread1 m_thread1;

private slots:
    void slot();// 在主函数中定义需要调用的槽函数
};

#endif // MAINWINDOW_H

thread1.cpp

#include "thread1.h"
#include <QDebug>

Thread1::Thread1(QThread *parent)
    : QThread(parent)
{

}

void Thread1::run()
{
    qDebug()<<u8"Thread1线程ID"<<QThread::currentThreadId();

    emit sigThread1();

    for(int i=0;i<10;i++)
    {
        qDebug()<<i;
    }
}

thread1.h

#ifndef THREAD1_H
#define THREAD1_H

#include <QThread>

class Thread1 : public QThread
{
    Q_OBJECT
public:
    explicit Thread1(QThread *parent = 0);

protected:
    virtual void run();

signals:
    void sigThread1();
};
#endif // THREAD1_H

结论:可以看出:emit发射信号后立马执行槽函数,没有任何等待;并且槽函数执行在Thread1线程中;

 


队列连接(Qt::QueuedConnection - 异步)

同一线程

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(this,SIGNAL(sig()),this,SLOT(slot()),Qt::QueuedConnection);

    emit sig();

    for(int i=0; i<10;i++)
    {
        qDebug()<<i;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slot()
{
    qDebug()<<u8"执行槽函数";
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "thread1.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

private slots:
    void slot();
signals:
    void sig();
};

#endif // MAINWINDOW_H

结论:可以看到:先执行完for循环(先把自己的事情处理完),当空闲后再执行槽函数。 

 

 

不同线程

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug()<<u8"主线程ID"<<QThread::currentThreadId();

    connect(&m_thread1,SIGNAL(sigThread1()),this,SLOT(slot()),Qt::QueuedConnection);

    m_thread1.start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slot()
{
    qDebug()<<u8"执行槽函数---线程ID"<<QThread::currentThreadId();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <thread1.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    Thread1 m_thread1;

private slots:
    void slot();

};
#endif // MAINWINDOW_H

thread1.cpp

#include "thread1.h"
#include <QDebug>

Thread1::Thread1(QThread *parent)
    : QThread(parent)
{

}
void Thread1::run()
{
    qDebug()<<u8"Thread1线程ID"<<QThread::currentThreadId();

    emit sigThread1();

    for(int i=0;i<10000;i++) //此处为10000次,加长时间,以便更清楚的观察现象
    {
        qDebug()<<i;
    }
}

thread1.h

#ifndef THREAD1_H
#define THREAD1_H

#include <QThread>

class Thread1 : public QThread
{
    Q_OBJECT
public:
    explicit Thread1(QThread *parent = 0);

protected:
    virtual void run();

signals:
    void sigThread1();
};

#endif // THREAD1_H

结论:

  • 可以看出:thread1线程发送信号后,thread1接着做自己的事,主线程同样接着做自己的事。
  • 当主线程空闲时,再执行槽函数,槽函数运行在主线程中。

 


锁定队列连接(Qt::BlockingQueuedConnection - 阻塞)

  • 代码参考上面的,将Qt::QueuedConnection改为Qt::BlockingQueuedConnection即可。
  • 可以看到:规律同Qt::QueuedConnection,不过thread1线程发送完信号后,会阻塞,直到主线程的槽函数返回,thread1线程才会继续向下执行。

 

标签:Qt,parent,mainwindow,参数,线程,第五个,include,MainWindow
From: https://www.cnblogs.com/zhuchunlin/p/18541548

相关文章

  • JVM 参数配置入门与优化案例
    文章目录JVM参数配置入门与优化案例基础内存参数配置堆内存(HeapMemory)元空间(Metaspace)新生代与老年代比例直接内存(DirectMemory)垃圾回收器(GC)设置OOM异常分析设置GC日志设置实战配置案例:Netty服务配置总结与优化建议JVM参数配置入门与优化案例在Java应用的......
  • 函数(概念、使用、参数、return、argument、函数方法、嵌套函数、立即执行函数)
    一、函数的概念函数:就是封装一段可被重复调用执行的代码块。通过代码块可以实现在需要的的重复使用,使用typeof检查一个函数对象时,会返回function函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口,简单理解:将很多衣服打包到一个行李箱,jQuer......
  • 终于弄懂了Python位置参数与关键字参数
    Python位置参数与关键字参数在Python函数的使用中,函数的参数是一种让调用者向函数传递信息的手段。函数可以通过参数接收外部提供的值,从而根据这些值执行特定的操作。本节我们将重点讲解位置参数和关键字参数两种参数类型,它们是定义和调用函数时最基础的参数形式。1.位置......
  • Qt构建与解析Json示例
    本文以B站UP主“明王讲QT”的【QT开发专题-天气预报】中的章节内容作为学习Qt中构建、解析Json的参考方法。1、Json文本{"info":{"asian":true,"captical":"beijing","founded":1949},"name":"China&qu......
  • Qt读写文件简单示例
    voidtestReadWriteFile(){//当前程序所在文件夹QStringdirPath=QCoreApplication::applicationDirPath();QStringpath=QDir::cleanPath(dirPath+QDir::separator()+"test.txt");qDebug()<<"Filepath:"<<path;......
  • 【MQTT】代理服务比较RabbitMQ、Mosquitto 和 EMQX
    前言目前要处理大量设备同时频繁发送数据的情况,MQTT协议确实是一个更优的选择,因为它特别适合需要低带宽和高效能的物联网应用,下面是对目前主流协议的对比数据截止日期:2024年11月10日基础设施后端:springcloud项目设备端:IOT设备,每秒上报数据对比项特性RabbitMQMosqui......
  • 开发人员,千万不要去碰那该死的业务参数,无论什么时候!
    你好呀,我是歪歪。前几天发了一个牢骚:本来只是单纯的吐槽一下,但是好多人对其中的细节比较感兴趣。大家都是搞技术的嘛,对于“踩BUG”这种喜闻乐见的事情,有兴趣是很正常的。其实我这个BUG,其实严格意义上不能叫做BUG,因为和程序无关,甚至和技术的关系都不算大。从标题上你也能猜......
  • 零声QT学习 一
    intmain(intargc,char*argv[]){QApplicationa(argc,argv); //QApplicationa(argc,argv),针对QWidget应用程序,管理和设置Qt程序的运行 //QGuiApplicationa(argc,argv),针对非QWidget应用程序,如QQuick //QcoreApplicationa(argc,argv),针对无界面的应用程序......
  • 常见 setup.exe 参数 有关 Setup 命令行参数的其他信息,请参阅 Setup Help 文件。有
    Windows安装程序安装或升级Windows。Setup.exe[/debughelp][/auto<upgrade;dataonly;clean>][/quiet][/installdrivers<driver_folder_path>][/noreboot][/installangpacks<language_packfolder_path>][/showoobe<none;full>][/unattend:<ans......
  • Qt边推流边录制/实时性好延迟低/16路1080P推流加录制只占1%CPU/优化到极致
    一、前言这个一边推流一边录制的功能,有很多用户提到过,之前因为时间的原因,一直没有搞,年初的时候索性抽空搞了下,也着实费了些功夫。推流用的是ffmpeg这个开源的牛逼的第三方库,搞音视频开发的人应该没人不认识这个库,养活了很多程序员以及厂家,甚至不乏一些大厂,如果能把ffmpeg搞精通,在......