事先声明:此篇博客非完全原创
一. 同步
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);