Я создал демо для изучения QObject, QThread и QT Signal / Slot в виде ссылок ниже
Идея такова:
Я создал ExtentQThread, экстент которого из QThread, и запускаю реализацию() функция, которая будет зацикливаться для loopTimeoutMsec (устанавливается в конструкторе) перед вызовом exec () (что заставляет его войти в свой цикл событий потока).Я создал один экземпляр ExtentQThread extQThread1 из основного с loopTimeoutMsec , установленным в 10000 .
Затем я создал два экземпляра ExtentQObject из основного потока. extQObject10 создан и перемещен в extQThread1 и extQObject11 , который не перемещен.
Ожидание теста:
- Слот extQObject11 запускается в основном потоке примерно (время ожидания = 5000): PASSED
- Слот extQObject10 работает на extQThread1 : PASSED
- Слот extQObject10 работает на extQThread1 около ( loopTimeoutMsec = 10000): НЕ ПРОЙДЕНО
[main.cpp]
#include <QCoreApplication>
#include <QTimer>
#include "extentqthread.h"
long baseMSecsSinceEpoch;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
baseMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << "Main thread 1" << QThread::currentThreadId();
// === test1
ExtentQThread extQThread1("extQThread1 created from main thread", 10000);
ExtentQObject extQObject10("extQObject10 created from main thread then moved to extQThread1");
extQObject10.moveToThread(&extQThread1);
ExtentQObject extQObject11("extQObject11 created from main thread");
extQThread1.start();
// 1.0 to test signal of extQObject10 which is moved to extQThread1
// and signal of extQObject11 which is not moved
long timeout = 5000;
QTimer::singleShot(timeout, [&extQThread1, &timeout]() {
qDebug() << "\n==" << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << "timeout" << timeout
<< "\n>> To test signal of extQObject10 which is moved to extQThread1 and signal of extQObject11 which is not moved"
<< "\n>> extQThread1.isRunning()" << extQThread1.isRunning();
});
QTimer::singleShot(timeout, &extQObject10, &ExtentQObject::onExtentQObjectFirstSlot);
QTimer::singleShot(timeout, &extQObject11, &ExtentQObject::onExtentQObjectFirstSlot);
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << "Main thread 2" << QThread::currentThreadId();
return a.exec();
}
[exteqthread.cpp]
#include "extentqthread.h"
extern long baseMSecsSinceEpoch;
ExtentQThread::ExtentQThread(QString name_, long loopTimeoutMsec_)
{
name = name_;
loopTimeoutMsec = loopTimeoutMsec_;
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "loopTimeoutMsec" << loopTimeoutMsec
<< "created on thread" << QThread::currentThreadId();
}
void ExtentQThread::run() {
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "STARTED on thread" << QThread::currentThreadId();
ExtentQObject extQObject("extQObject created from (" + name + ")");
connect(this, &ExtentQThread::runFirstSlot, &extQObject, &ExtentQObject::onExtentQObjectFirstSlot);
if (loopTimeoutMsec < 0) {
while(1) {};
} else {
QThread::msleep(loopTimeoutMsec);
}
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "before exec() on thread" << QThread::currentThreadId();
exec();
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "after exec() on thread" << QThread::currentThreadId();
if (loopTimeoutMsec < 0) {
while(1) {};
} else {
QThread::msleep(loopTimeoutMsec);
}
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "STOPPED on thread" << QThread::currentThreadId();
}
void ExtentQThread::onExtentQThreadFirstSlot() {
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "run on thread" << QThread::currentThreadId();
Q_EMIT runFirstSlot();
}
[stretqobject.cpp]
#include "extentqobject.h"
extern long baseMSecsSinceEpoch;
ExtentQObject::ExtentQObject(QString name_)
{
name = name_;
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "created on thread" << QThread::currentThreadId();
}
void ExtentQObject::onExtentQObjectFirstSlot() {
qDebug() << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << Q_FUNC_INFO
<< "instance" << name
<< "run on thread" << QThread::currentThreadId();
}
Вот вывод
0 Main thread 1 0x7fdc8f3f3740
1 ExtentQThread::ExtentQThread(QString, long int) instance "extQThread1 created from main thread" loopTimeoutMsec 10000 created on thread 0x7fdc8f3f3740
1 ExtentQObject::ExtentQObject(QString) instance "extQObject10 created from main thread then moved to extQThread1" created on thread 0x7fdc8f3f3740
1 ExtentQObject::ExtentQObject(QString) instance "extQObject11 created from main thread" created on thread 0x7fdc8f3f3740
1 Main thread 2 0x7fdc8f3f3740
1 virtual void ExtentQThread::run() instance "extQThread1 created from main thread" STARTED on thread 0x7fdc8aa03700
1 ExtentQObject::ExtentQObject(QString) instance "extQObject created from (extQThread1 created from main thread)" created on thread 0x7fdc8aa03700
== 4754 timeout 5000
>> To test signal of extQObject10 which is moved to extQThread1 and signal of extQObject11 which is not moved
>> extQThread1.isRunning() true
4754 void ExtentQObject::onExtentQObjectFirstSlot() instance "extQObject11 created from main thread" run on thread 0x7fdc8f3f3740
10001 virtual void ExtentQThread::run() instance "extQThread1 created from main thread" before exec() on thread 0x7fdc8aa03700
14756 void ExtentQObject::onExtentQObjectFirstSlot() instance "extQObject10 created from main thread then moved to extQThread1" run on thread 0x7fdc8aa03700
Как я понимаю, я ожидаю: ExtentQObject :: onExtentQObjectFirstSlot () instance "extQObject10созданный из основного потока, затем перемещенный в extQThread1 ", запущенный в потоке 0x7fdc8aa03700 , работающий со скоростью около 10000 (мсек) вместо 14756 (мсек).поскольку сигнал излучается со скоростью 5000 (мсек), а exec (), который входит в ExtentQthread, запускается после 10000 (мсек), и он должен обрабатывать onExtentQObjectFirstSlot затем.
Может кто-нибудь дать какое-нибудь объяснение?
////
- Я пытался перейти с экземпляра QTimer :: singleShot на экземпляр QTimer, который дал ожидаемое поведение (разница, как показано ниже)
diff --git a / main.cpp b / main.cpp index ed45d23..0ebabf3 100644 --- a / main.cpp +++ b / main.cpp @@ -25,14 +25,17 @@ int main (int argc, char * argv [])
// 1.0 to test signal of extQObject10 which is moved to extQThread1
// and signal of extQObject11 which is not moved
+ QTimer timer;
+ timer.setSingleShot(true);
long timeout = 5000;
- QTimer::singleShot(timeout, [&extQThread1, &timeout]() {
+ QObject::connect(&timer, &QTimer::timeout, [&extQThread1, &timeout]() {
qDebug() << "\n==" << QDateTime::currentMSecsSinceEpoch() - baseMSecsSinceEpoch << "timeout" << timeout
<< "\n>> To test signal of extQObject10 which is moved to extQThread1 and signal of extQObject11 which is not moved"
<< "\n>> extQThread1.isRunning()" << extQThread1.isRunning();
});
- QTimer::singleShot(timeout, &extQObject10, &ExtentQObject::onExtentQObjectFirstSlot);
- QTimer::singleShot(timeout, &extQObject11, &ExtentQObject::onExtentQObjectFirstSlot);
+ QObject::connect(&timer, &QTimer::timeout, &extQObject10, &ExtentQObject::onExtentQObjectFirstSlot);
+ QObject::connect(&timer, &QTimer::timeout, &extQObject11, &ExtentQObject::onExtentQObjectFirstSlot);
+ timer.start(timeout);