问题描述
让我们考虑两个QObjects
,senderObject
类型的SenderObject
和receiverObject
类型的ReceiverObject
的情况。 senderObject
是在辅助线程上创建的,而receiverObject
是在主线程上创建的。现在,假设SenderObject
有一个信号somethingsChanged
,并考虑以下代码片段:
代码段1:
int main(int argc,char *argv[]) {
QCoreApplication a(argc,argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.movetoThread(&t);
ReceiverObject receiverObject = new ReceiverObject();
//in this case we kNow for a fact that receiverObject's
//onSomethingsChanged() will be called on the main thread
QObject::connect(senderObject,&SenderObject::somethingsChanged,receiverObject,&ReceiverObject::onSomethingsChanged,Qt::QueuedConnection);
t.start();
return a.exec();
}
现在让我们考虑以下代码片段:
代码段2:
int main(int argc,argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.movetoThread(&t);
//where will qDebug() << "Hello,world" be executed?
//On the main thread again since the lambda lives on the main thread?
QObject::connect(senderObject,[]{qDebug << "Hello,world";});
t.start();
return a.exec();
}
Slampet2中的lambda是否也会在主线程上执行,因为lambda已经在主线程上声明了,还是会在与senderObject
相同的线程中执行?
解决方法
这是我们的课程SenderObject:
class Sender : public QObject {
Q_OBJECT
public:
explicit Sender() : QObject() {
_timer.setInterval(1000);
connect(&_timer,&QTimer::timeout,this,[this] { emit somethingsChanged(); });
_timer.start();
}
signals:
void somethingsChanged();
private:
QTimer _timer;
};
由于没有QObject::connect
的重载将使用lambda和Qt
连接类型参数,因此Snippet2将在发送方的线程(即工作线程)中执行。
为了强制lambda在主线程上执行,这是一种解决方法:
int main(int argc,char *argv[]) {
QCoreApplication a(argc,argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.moveToThread(&t);
QObject::connect(senderObject,&SenderObject::somethingsChanged,new QObject,[]{qDebug << "Hello,world";},Qt::QueuedConnection);
t.start();
return a.exec();
}
由于在主线程上调用了new QObject
,因此lambda也将在主线程上执行。
或者,如果我们不希望看到new
,这将起作用:
int main(int argc,argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.moveToThread(&t);
QObject object;
QObject::connect(senderObject,&object,Qt::QueuedConnection);
t.start();
return a.exec();
}
或者,甚至更好的解决方案是使用qApp
,它是应用程序的一个实例,是一个单例,可以在任何地方使用。
int main(int argc,qApp,Qt::QueuedConnection);
t.start();
return a.exec();
}