qt中信号槽第五个参数

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线程才会继续向下执行。
    在这里插入图片描述
  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,我们可以得知QT信号第五个参数是连接类型。连接类型有五种,分别是: 1. Qt::AutoConnection:自动连接方式,如果信号在同一线程,则采用直接连接方式,否则采用队列连接方式。 2. Qt::DirectConnection:直接连接方式,当信号发射时,函数会立即执行,无论信号在哪个线程。 3. Qt::QueuedConnection:队列连接方式,当信号发射时,函数会被放入接收者对象所在的线程的事件队列,等待事件循环处理。 4. Qt::BlockingQueuedConnection:阻塞队列连接方式,当信号发射时,函数会被放入接收者对象所在的线程的事件队列,但是发射信号的线程会被阻塞,直到函数执行完毕。 5. Qt::UniqueConnection:唯一连接方式,如果信号已经连接到了某个函数,再次连接时会失败。 下面是一个例子,演示了如何使用第五个参数来连接信号: ```cpp // 定义一个信号 class Sender : public QObject { Q_OBJECT signals: void mySignal(int value); }; // 定义一个函数 class Receiver : public QObject { Q_OBJECT public slots: void mySlot(int value) { qDebug() << "Received value: " << value; } }; // 在main函数连接信号 int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Sender sender; Receiver receiver; // 使用Qt::QueuedConnection连接信号 QObject::connect(&sender, SIGNAL(mySignal(int)), &receiver, SLOT(mySlot(int)), Qt::QueuedConnection); // 发射信号 emit sender.mySignal(100); return a.exec(); } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值