信号与槽

Signals and Slots AcrossThreads

Qt支持了几种信号--槽的连接方式:

1.     Auto Connection (默认):如果如果信号的发送方与接收方是处于同一个线程,这个连接就是 Direct Connection,否则就跟 Queued Connection一样。

2.    Direct Connection :当信号发出之后,槽会立即被调用。槽函数是在信号发送方的线程中运行的,不需要接收方的线程。

3.    Queued Connection:当控制权回到接收方线程时调用槽函数。槽函数是在接收方的线程中运行的。

4.    Blocking Queued Connection :调用方式跟 Queued Connection一样,区别在于,当前线程会被阻塞直到槽函数返回。

5.    Unique Connection :这种方式跟 Auto Connection一样,但是只有当不存在一个相同的连接时才会创建一个连接。如果已经存在相同的连接,则不会创建连接,connect()返回false

可以在connect()添加参数指定连接类型。需要注意的一点是:如果信号发送方和接收方处于不同的线程,而且接收方线程运行着一个事件循环,此时用Direct Connection是不安全,原因跟调用一个对象的函数,而这个对象处于另外的线程,那样的调用是不安全。

QObject::connect() 本身是线程安全的。

下面通过结果例子验证一下:

 

class Receiver:publicQObject

{

       Q_OBJECT

public:

 

       voidsendmes()

       {

              emitemitSignal("emit message from A  To B");

       }

       Receiver()

       {

 

       }

protected slots:

       voidmessageSlot(QString mes)

       {

              qDebug()<<mes;

       }

signals:

       voidemitSignal(QString mes);

 

private:

};

int main(int argc, char *argv[])

{

       QApplication a(argc, argv);

       Receiver objA,objB;

      

       QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)));

       qDebug()<<"beforeemitsignal ";

       objA.sendmes();

       qDebug()<<"afteremitsignal ";

       returna.exec();

}

objA,objB;出于同一个线程,所以connect的连接类型是Direct Connection

由输出我们可以看出执行顺序,

 

如果我们写了两句连接:

QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)));

       QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)));

 

就会相应的有两句消息输出:


 

如果指定了连接类型Qt::UniqueConnection ,就会只有一句消息输出了。

QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)),Qt::UniqueConnection );

QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)),Qt::UniqueConnection);

 

int main(int argc, char *argv[])

{

       QApplication a(argc, argv);

       QThread *thread = new QThread;

       thread->start();

       Receiver objA,objB;

       objB.moveToThread(thread);

       QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)) );

       qDebug()<<"beforeemitsignal ";

       objA.sendmes();

       qDebug()<<"afteremitsignal ";

       returna.exec();

}

如果我们把objB放到另外的线程,connect的连接类型应该是Queued Connection 

 

int main(int argc, char *argv[])

{

       QApplication a(argc, argv);

       QThread *thread = new QThread;

       thread->start();

       Receiver objA,objB;

       objB.moveToThread(thread);

QObject::connect(&objA,SIGNAL(emitSignal(QString)),&objB,SLOT(messageSlot(QString)) ,Qt::BlockingQueuedConnection);

       qDebug()<<"beforeemitsignal ";

       objA.sendmes();

       qDebug()<<"afteremitsignal ";

       returna.exec();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值