我想从QtConcurrent :: runQtConcurrent ::运行发射信号
这个函数中发出一个Qt信号这可能吗?好像我的插槽永远不会被调用。所有的信号,插槽和函数都是同一个类对象的一部分。我试图在主线程和从线程中建立连接。我真的不在乎信号和插槽是否在同一个线程中,我只是想让它发生。
由于
我想从QtConcurrent :: runQtConcurrent ::运行发射信号
这个函数中发出一个Qt信号这可能吗?好像我的插槽永远不会被调用。所有的信号,插槽和函数都是同一个类对象的一部分。我试图在主线程和从线程中建立连接。我真的不在乎信号和插槽是否在同一个线程中,我只是想让它发生。
由于
可以使用Qt::QueuedConnection
用于该连接(将它传递给connect
呼叫该建立连接),由于信号将总是从比所述接收器对象的线程不同的线程发出的。
的Qt::AutoConnection
也会做同样的事情,并且信号添加到接收对象的线程的事件队列。
如果接收线程被阻塞,因而从未重新进入事件队列,信号不能被接收对象的时隙中接收。
你真的应该使用QFuture和QFutureWatcher与QtConcurrent ::的run()。
以下使用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);
}
这是不正确的:默认的自动连接将做的工作就好了。 –
@KubaOber:你错了。 OP表示所有插槽和信号都属于一个对象。因此,AutoConnection将评估为DirectConnection。这可能不是OP想要的,因为这要求槽以线程安全的方式使用对象。这种同步必须在这种情况下手动完成。 QueuedConnection将消除手动同步的需要,因为该槽将在对象所在的线程中调用。 Qt将处理实现该操作所需的同步。 – smerlin
发件人的对象无关紧要。发送和接收线程之间的比较是在信号被发射的时间完成的,并且在当前* *线程('的QThread :: currentThread')和* *目标线程('接收机 - >螺纹()')之间进行。 *发送对象的*线程在该确定中没有任何形式。 –