Je ne peux pas produire un exemple très simple pour commencer avec Qt multi-thread. J’ai lu beaucoup de messages et de tutoriels mais cela ne fonctionne toujours pas.
Avoir un travailleur de fond indépendant de l’interface graphique. Oh wow…
Un exemple simple:
Engine
QMainWindow
QTimer
qui imprime un nombre Mais si vous cliquez sur la barre de titre de l’interface graphique tout en maintenant le bouton gauche de la souris enfoncé (c.-à-d. Sur le bouton de réduction), le compteur s’arrête ! Même s’il a été créé dans un environnement non graphique et déplacé dans un autre thread!
main.cpp
#include "engine.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); Engine e; return a.exec(); }
moteur.h
#ifndef ENGINE_H #define ENGINE_H #include #include #include #include "mainwindow.h" class Engine : public QObject { Q_OBJECT public: explicit Engine(QObject *parent = 0); private: MainWindow mainWindow; QThread *thread; QTimer *timer; private slots: void foo(); }; #endif // ENGINE_H
moteur.c
#include "engine.h" #include Engine::Engine(QObject *parent) : QObject(parent) { thread = new QThread(this); timer = new QTimer(); timer->setInterval(100); connect(timer, &QTimer::timeout, this, &Engine::foo); connect(thread, &QThread::started, timer, static_cast(&QTimer::start)); timer->moveToThread(thread); thread->start(); mainWindow.show(); } void Engine::foo() { static int i; qDebug() << ++i; }
QMainWindow
ne contient aucun code.
Fondamentalement, Qt a un thread qui traite l’interface graphique (généralement le thread principal). Tous les objects spécifiques à ce fil seront bloqués par l’interface graphique. Vous devez conserver l’interface graphique en dehors de vos partenaires en interaction.
Pour être plus spécifique, votre object Engine
réside dans le thread graphique / principal. Même si votre timer est envoyée à un thread de travail, ses signaux sont envoyés au slot foo()
dans le thread principal.
Vous devez désactiver Engine
et la fenêtre principale pour que Engine
puisse résider dans son propre thread et traiter les signaux lorsque l’interface graphique est bloquée.
On dirait que vous avez déplacé une instance de QTimer dans votre thread personnalisé, mais que vous n’avez pas déplacé une instance de moteur dans ce thread; par conséquent, le foo slot de la classe Engine sera exécuté dans le thread principal.
Je peux vous suggérer d’utiliser une instance supplémentaire de la classe dérivée de QObject au sein de la classe Engine et de la déplacer vers votre nouveau thread dans le constructeur du moteur.
Avec les modifications suivantes, la solution fonctionne correctement, même avec le bouton de réduction activé (j’ai commenté des endroits où j’ai ajouté ou modifié quoi que ce soit. J’ai également ajouté la nouvelle classe dérivée de QObject, EngineWorker ):
Moteur.h
#ifndef ENGINE_H #define ENGINE_H #include #include #include #include "mainwindow.h" #include "engineworker.h" class Engine : public QObject { Q_OBJECT public: explicit Engine(QObject *parent = 0); private: MainWindow mainWindow; QThread *thread; QTimer *timer; //additional QObject-derived class EngineWorker *worker; private slots: void foo(); }; #endif // ENGINE_H
Engine.cpp
#include "engine.h" #include Engine::Engine(QObject *parent) : QObject(parent) { thread = new QThread(this); timer = new QTimer(); //Creating instance of Engine worker worker = new EngineWorker(); timer->setInterval(100); //Connecting Engine worker' foo slot to timer connect(timer, &QTimer::timeout, worker, &EngineWorker::foo); connect(thread, &QThread::started, timer, static_cast(&QTimer::start)); timer->moveToThread(thread); //Moving worker to custom thread worker->moveToThread(thread); thread->start(); mainWindow.show(); } void Engine::foo() { static int i; qDebug() << ++i; }
EngineWorker.h
#ifndef ENGINEWORKER_H #define ENGINEWORKER_H #include #include class EngineWorker : public QObject { Q_OBJECT public: explicit EngineWorker(QObject *parent = 0); signals: public slots: void foo(); }; #endif // ENGINEWORKER_H
EngineWorker.cpp
#include "engineworker.h" EngineWorker::EngineWorker(QObject *parent) : QObject(parent) { } //foo slot of EngineWorker class void EngineWorker::foo() { static int j; qDebug() <<"Worker: "<< ++j; }