Qt使用QueuedConnection将两个信号连接在一起

das*_*esy 25 qt signals thread-safety slot

Qt 文档说明可以将两个信号连接在一起:

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

我试过了:

connect(x, SIGNAL(S()), y, SIGNAL(func()));
Run Code Online (Sandbox Code Playgroud)

它的工作原理如上所述,但Qt文档仍在继续:

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

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

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

Ame*_*aki 29

它不应该与信号/插槽连接有很大不同.我们来看看信号/时隙的基本机制.每个线程中都有一个事件队列,用于维护已发出但尚未处理的信号(事件).因此,只要执行返回到事件循环,就会处理队列.事件循环本身不处理事件.相反,它将它们传递给对象,以便它们可以处理它.在这种特殊情况下,我认为该对象将发出另一个将插入队列的信号.当执行返回到事件循环时,新信号再次由对象处理.这是一个证明上述论点的测试.

如果您运行附加的代码,输出将是:

before signal() 
after signal() 
slot() called
Run Code Online (Sandbox Code Playgroud)

这意味着定义一个在线程之间排队的信号 - 信号连接类型具有预期的排队行为,拒绝它始终是立即的参数.如果将其定义为direct,则输出为:

before signal()
slot() called 
after signal()
Run Code Online (Sandbox Code Playgroud)

正如所料.它不会产生任何错误或警告,并且程序也不会崩溃.但是这个简单的例子并不能证明它适用于大型复杂的程序.

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();
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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";
}
Run Code Online (Sandbox Code Playgroud)