信号与槽连接方式(同步和异步)

事先声明:此篇博客非完全原创

一. 同步
synchronous.h

#ifndef SYNC_H
#define SYNC_H

#include <QObject>
#include <QDebug>

class MyTestA : public QObject
{
    Q_OBJECT
public:
    void emitSignal()
    {
        signalMyTestA();
    }

public slots:
    void slotMyTestA()
    {
        qDebug()<<"slotMyTestA is called.";
    }
signals:
    void signalMyTestA();
};


class MyTestB : public QObject
{
    Q_OBJECT
public slots:
    void slotMyTestB()
    {
        qDebug()<<"slotMyTestB is called.";
    }
signals:
    void signalMyTestB();
};


#endif // SYNC_H

main.cpp

#include <QApplication>

#include "synchronous.h"
#include "asynchronous.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

	MyTestA a;
	MyTestB b;		
	QObject::connect(&a,SIGNAL(signalMyTestA()),&b,SLOT(slotMyTestB()));//a和b都在主线程中-->
//    a.emitSignal();// <--并且发信号也在主线程中,同步调用

    return app.exec();
}

二. 异步
场景一:
asynchronous.h

#当sender和receiver在同一线程时,就是同步模式,而在不同线程时,则是异步模式,其实这是错误的观念。

class MyTestA : public QObject
{
    Q_OBJECT
public:
    void emitSignal()
    {
        signalMyTestA();
    }

public slots:
    void slotMyTestA()
    {
        qDebug()<<"slotMyTestA is called.";
    }
signals:
    void signalMyTestA();
};


class MyTestB : public QObject
{
    Q_OBJECT
public slots:
    void slotMyTestB()
    {
        qDebug()<<"slotMyTestB is called.";
    }
signals:
    void signalMyTestB();
};


extern MyTestB *g_pMyTestB;
class MyTestC : public QThread
{
    Q_OBJECT
public:

    void run()
    {
        MyTestA a;
        connect(&a,SIGNAL(signalMyTestA()),g_pMyTestB,SLOT(slotMyTestB()));//a在子线程中,b在主线程中-->
        a.emitSignal();// <--发信号在子线程中,异步调用
        exec();

    }

public slots:
    void slotMyTestC()
    {
        qDebug()<<"slotMyTestC is called.";
    }
signals:
    void signalMyTestC();

};

main.cpp

#include <QApplication>

#include "synchronous.h"
#include "asynchronous.h"

MyTestB *g_pMyTestB = NULL;

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
	MyTestB b;
	g_pMyTestB = &b;
	MyTestC c;
	c.start();
	 
	return app.exec();
}

场景二:
asynchronous.h

//在Auto模式下,如果sender的触发时所处的线程和receiver不同,也会是异步调用。

class MyTestA : public QObject
{
    Q_OBJECT
public:
    void emitSignal()
    {
        signalMyTestA();
    }

public slots:
    void slotMyTestA()
    {
        qDebug()<<"slotMyTestA is called.";
    }
signals:
    void signalMyTestA();
};

class MyTestB : public QObject
{
    Q_OBJECT
public slots:
    void slotMyTestB()
    {
        qDebug()<<"slotMyTestB is called.";
    }
signals:
    void signalMyTestB();
};

extern MyTestB *g_pMyTestB;
extern MyTestA *g_pMyTestA;
class MyTestC : public QThread
{
    Q_OBJECT
public:

    void run()
    {
        g_pMyTestA->emitSignal();//<--但是发信号在子线程中,异步调用
        exec();
    }

public slots:
    void slotMyTestC()
    {
        qDebug()<<"slotMyTestC is called.";
    }
signals:
    void signalMyTestC();
};

main.cpp

#include <QApplication>

#include "synchronous.h"
#include "asynchronous.h"

MyTestB *g_pMyTestB = NULL;
MyTestA *g_pMyTestA = NULL;
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

	MyTestA a;
	g_pMyTestA = &a;
	MyTestB b;
	g_pMyTestB = &b;
	QObject::connect(&a,SIGNAL(signalMyTestA()),&b,SLOT(slotMyTestB()));//a和b都在主线程中-->
	MyTestC c;
	c.start();
	
	return app.exec();
}


最终得出的结论:只有当信号的发送者和接收者处于同一个线程,并且发送者触发信号时和接收者处于同一个线程,才会是同步调用。

determine if this connection should be sent immediately or put into
the event queue
if ((c->connectionType == Qt::AutoConnection
&& (currentThreadData != sender->d_func()->threadData
|| receiver->d_func()->threadData != sender->d_func()->threadData))
|| (c->connectionType == Qt::QueuedConnection)) {
queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
continue;
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
blocking_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
continue;
}

摘自qobject.cpp


QT在设置信号与槽的时候出现执行两次槽函数

修改方法:

将 connect(ui.messageButton,SIGNAL(pressed()),this,SLOT(on_messageButton_clicked()));
更改为:

connect(ui.messageButton,SIGNAL(pressed()),this,SLOT(on_messageButton_clicked()),Qt::UniqueConnection);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值