代码之家  ›  专栏  ›  技术社区  ›  Jaa-c

从另一个线程发出信号安全吗?

  •  2
  • Jaa-c  · 技术社区  · 7 年前

    从另一个线程在一个对象上发出信号安全吗(如果插槽是按如下方式连接的) QueuedConnection )? 我找不到一个具体的文件,其中提到这一点,最多 relevant quote

    QObject是可重入的。它的大多数非GUI子类,比如QTimer, qtcsocket、QUdpSocket和QProcess也是可重入的,因此 可以从多个线程同时使用这些类。 请注意,这些类的设计目的是从 在单个线程内; 在一个线程中创建对象并调用 .

    这表明它可能不正常,这是否也适用于信号?有一个 QMutexLocker 里面 QMetaObject::activate ,所以在我看来它可能是线程安全的。。。?

    #include <QCoreApplication>
    #include <QTimer>
    #include <thread>
    #include <iostream>
    
    struct Foo : public QObject
    {
        Q_OBJECT
    public:
        Foo(QObject* parent) : QObject(parent) {}
    
    public slots:
        void run()
        {
            connect(this, &Foo::signal, this, [] { std::cout << "activated"; }, Qt::QueuedConnection);
    
            std::thread t([this] { emit signal(); });
            if (t.joinable()) t.join();
        }
    
    signals:
        void signal() const;
    };
    
    #include "main.moc"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        Foo* b = new Foo(&a);
        QTimer::singleShot(0, b, &Foo::run);
        return a.exec();
    }
    
    1 回复  |  直到 7 年前
        1
  •  6
  •   ixSci    7 年前

    Qt基于事件队列。每个Qt线程都有自己的队列和相关的事件循环。因此,当您遇到这样一种情况:有两个不同的对象存在于两个不同的线程中,其中一个通过信号/插槽机制(通过自动或排队连接)连接到另一个线程时,在发射过程中会发生以下情况:信号中的代码创建一个事件并将其发送到对象接收器的队列。接收器的事件循环在队列中运行,找到发布的事件并执行适当的槽。

    队列保证是线程安全的,因此跨线程发出信号是绝对安全的。你问题中的引语是关于你做出决定的情况 直接呼叫 关于居住的物体 T1 T2 .

    有一篇关于线程、qobject、信号、插槽以及所有内容如何相互关联的文章: Threads Events QObjects


    关于有问题的代码。您有一个排队连接,这意味着发送方和接收方是在一个线程中还是在不同的线程中并不重要。发送方和接收方是两个对象还是同一个对象并不重要。上述程序将是相同的。如果你创建了一个自动连接,那么它将有一个直接呼叫,但你没有。和一个相关的报价从 documentation :

    因为信号发射是线程安全的

        2
  •  1
  •   Mohamd Alhawi    5 年前

    因此,您应该从threadone发出一个信号,并在threadtow中连接它(接收它),并根据信号类型执行一些线程代码 如果您试图直接执行代码,您将得到这个错误

    QObject::setParent:无法设置父级,新父级位于其他线程中