#c #multithreading #qt #qwidget #qthread
#c #многопоточность #qt #qwidget #qthread
Вопрос:
Давайте рассмотрим сценарий из двух 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(amp;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, amp;SenderObject::somethingsChanged,
receiverObject, amp;ReceiverObject::onSomethingsChanged, Qt::QueuedConnection);
t.start();
return a.exec();
}
Теперь давайте рассмотрим следующий фрагмент кода:
Фрагмент2:
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.moveToThread(amp;t);
//where will qDebug() << "Hello, world" be executed?
//On the main thread again since the lambda lives on the main thread?
QObject::connect(senderObject, amp;SenderObject::somethingsChanged,
[]{qDebug << "Hello, world";});
t.start();
return a.exec();
}
Будет ли лямбда-код в Snippet2 выполняться в основном потоке также, поскольку лямбда-код был объявлен в основном потоке, или он будет выполняться в том же потоке, senderObject
что и?
Ответ №1:
Вот наш класс SenderObject:
class Sender : public QObject {
Q_OBJECT
public:
explicit Sender() : QObject() {
_timer.setInterval(1000);
connect(amp;_timer, amp;QTimer::timeout, this,
[this] { emit somethingsChanged(); });
_timer.start();
}
signals:
void somethingsChanged();
private:
QTimer _timer;
};
Поскольку нет перегрузки QObject::connect
, которая будет принимать лямбда-код и Qt
параметр типа соединения, Snippet2 будет выполняться в потоке отправителя, который является рабочим потоком.
Чтобы заставить лямбду выполняться в основном потоке, вот обходной путь:
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.moveToThread(amp;t);
QObject::connect(senderObject, amp;SenderObject::somethingsChanged, new QObject,
[]{qDebug << "Hello, world";}, Qt::QueuedConnection);
t.start();
return a.exec();
}
Поскольку new QObject
вызывается в основном потоке, лямбда-код также будет выполняться в основном потоке.
Или, если нам не нравится видеть new
, это то, что будет работать:
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.moveToThread(amp;t);
QObject object;
QObject::connect(senderObject, amp;SenderObject::somethingsChanged, amp;object,
[]{qDebug << "Hello, world";}, Qt::QueuedConnection);
t.start();
return a.exec();
}
Или, даже лучшим решением будет использовать qApp
, который является экземпляром приложения и синглтона и доступен из любого места.
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QThread t;
SenderObject senderObject = new SenderObject();
senderObject.moveToThread(amp;t);
QObject::connect(senderObject, amp;SenderObject::somethingsChanged, qApp,
[]{qDebug << "Hello, world";}, Qt::QueuedConnection);
t.start();
return a.exec();
}