2011-08-18 86 views
2

我想从QtConcurrent :: runQtConcurrent ::运行发射信号

这个函数中发出一个Qt信号这可能吗?好像我的插槽永远不会被调用。所有的信号,插槽和函数都是同一个类对象的一部分。我试图在主线程和从线程中建立连接。我真的不在乎信号和插槽是否在同一个线程中,我只是想让它发生。

由于

回答

1

可以使用Qt::QueuedConnection用于该连接(将它传递给connect呼叫该建立连接),由于信号将总是从比所述接收器对象的线程不同的线程发出的。

Qt::AutoConnection也会做同样的事情,并且信号添加到接收对象的线程的事件队列。

如果接收线程被阻塞,因而从未重新进入事件队列,信号不能被接收对象的时隙中接收。

+0

这是不正确的:默认的自动连接将做的工作就好了。 –

+0

@KubaOber:你错了。 OP表示所有插槽和信号都属于一个对象。因此,AutoConnection将评估为DirectConnection。这可能不是OP想要的,因为这要求槽以线程安全的方式使用对象。这种同步必须在这种情况下手动完成。 QueuedConnection将消除手动同步的需要,因为该槽将在对象所在的线程中调用。 Qt将处理实现该操作所需的同步。 – smerlin

+0

发件人的对象无关紧要。发送和接收线程之间的比较是在信号被发射的时间完成的,并且在当前* *线程('的QThread :: currentThread')和* *目标线程('接收机 - >螺纹()')之间进行。 *发送对象的*线程在该确定中没有任何形式。 –

2

以下使用Qt 4.8.7工作得很好。信号从工作线程发出,并在主线程中消耗。我们断言该槽在主线程中运行,并且该仿函数在工作线程中运行。

// https://github.com/KubaO/stackoverflown/tree/master/questions/concurrent-emit-qt4-7114421 
#include <QtCore> 

class Helper : public QObject { 
    Q_OBJECT 
public: 
    int n = 0; 
    Q_SLOT void increment() { 
     Q_ASSERT(QThread::currentThread() == qApp->thread()); 
     n++; 
    } 
}; 

int main(int argc, char **argv) 
{ 
    QCoreApplication app(argc, argv); 
    Helper helper; 
    Q_ASSERT(helper.n == 0); 
    QtConcurrent::run([&]{ 
     Q_ASSERT(QThread::currentThread() != qApp->thread()); 
     QObject src; 
     QObject::connect(&src, SIGNAL(destroyed(QObject*)), &helper, SLOT(increment())); 
     QObject::connect(&src, SIGNAL(destroyed(QObject*)), &app, SLOT(quit())); 
    }); 
    app.exec(); 
    Q_ASSERT(helper.n == 1); 
} 

#include "main.moc" 

在Qt 5,你不需要辅助类来证明它的工作原理:

#include <QtConcurrent> 

int main(int argc, char **argv) 
{ 
    QCoreApplication app(argc, argv); 
    int n = 0; 
    Q_ASSERT(n == 0); 
    QtConcurrent::run([&]{ 
     Q_ASSERT(QThread::currentThread() != qApp->thread()); 
     QObject src; 
     QObject::connect(&src, &QObject::destroyed, &app, [&]{ 
     Q_ASSERT(QThread::currentThread() == qApp->thread()); 
     n ++; 
     qApp->quit(); 
     }); 
    }); 
    app.exec(); 
    Q_ASSERT(n == 1); 
}