使用QueuedConnection连接两个Qt信号

25

Qt 文档指出,可以将两个信号连接在一起:

甚至可以直接将一个信号连接到另一个信号。

我尝试过:

connect(x, SIGNAL(S()), y, SIGNAL(func()));

它按照提到的方式工作,但Qt文档继续说:

(每当第一个信号被发出时,这将立即发出第二个信号。)

这是否意味着QueuedConnection将无法正常工作?我能否跨线程连接两个信号?

我之所以问这个问题是因为通过避免这种情况,我解决了应用程序中一类崩溃问题,但我不确定这是否与连接信号有关。


2
你有尝试过创建跨线程信号连接的测试用例吗?在原始信号(在一个线程中)之前和之后打印一条消息,并在第二个信号的插槽(在第二个线程中)连接中。在第二个线程中,在事件循环中重复调用持续一秒或两秒钟的sleep,以使该线程中的插槽被同步调用第一个线程或在第二个线程中异步调用更加明显。 - tmpearce
@tmpearce- 好建议,我会尝试并在这里发布结果。 - dashesy
2
那么,你试过了吗? - gnovice
文档措辞不佳。QueuedConnection会按照应有的方式排队连接。来源:个人经验。我经常在线程边界上使用SIGNAL/SLOT连接。 - cgmb
@Slavik81 - 我认为个人经验(即经过测试的内容)在这里是一个很好的答案,如果您能将其发布为答案,我会非常感激。 - dashesy
2个回答

29
它与信号/插槽连接应该没有太大的区别。让我们来看一下信号/插槽的底层机制。每个线程中都有一个事件队列,用于维护已发出但尚未处理的信号(事件)。因此,每当执行返回到事件循环时,就会处理队列。事件循环本身不处理事件。而是将它们传递给对象以便它们进行处理。在这种特殊情况下,我想对象会发出另一个信号,该信号将被插入队列中。当执行返回到事件循环时,新信号再次由对象处理。以下是一个测试,证明了以上论点。
如果您运行附加的代码,则输出将为:
before signal() 
after signal() 
slot() called

这意味着将信号与信号之间的连接类型定义为队列化,线程之间的行为会按预期进行,会拒绝那些总是立即执行的参数。如果您将其定义为直接连接,则输出结果将如下所示:
before signal()
slot() called 
after signal()

如预期的那样,它没有生成任何错误或警告,程序也不会崩溃。然而,这个简单的例子并不能证明它同样适用于一个大型且复杂的例子。

main.cpp:

#include <QtGui/QApplication>
#include "dialog.h"
#include "testssconnection.h"

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

    TestSignalSignalConnection * t = new TestSignalSignalConnection();
    t->start();

    return a.exec();
}

testssconnection.h:

#ifndef TESTSSCONNECTION_H
#define TESTSSCONNECTION_H

#include <QObject>
#include <QThread>

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

    void run();

signals:
    void signal1();
    void signal2();

public slots:
    void slot();
};

#endif // TESTSSCONNECTION_H

testssconnection.cpp:

#include "testssconnection.h"
#include <QtCore>

TestSignalSignalConnection::TestSignalSignalConnection(QObject *parent) :
    QThread(parent)
{
}

void TestSignalSignalConnection::run()
{
    TestSignalSignalConnection *t = new TestSignalSignalConnection();

    this->connect(this,SIGNAL(signal1()),t,SIGNAL(signal2()), Qt::QueuedConnection);
    t->connect(t,SIGNAL(signal2()), t,SLOT(slot()), Qt::DirectConnection);

    qDebug() << "before signal()";
    emit signal1();
    qDebug() << "after signal()";

    exec();
}

void TestSignalSignalConnection::slot()
{
    qDebug() << "slot() called";
}

1

1
谢谢提供链接,但我更希望能够得到一些例子作为未来搜索者的明确证据。 - dashesy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接