Technologies multithread dans Qt
Qt propose de nombreuses classes et fonctions permettant de travailler avec des threads. Vous trouverez ci-dessous quatre approches différentes que les programmeurs Qt peuvent utiliser pour implémenter des applications multithread.
QThread : API de bas niveau avec boucles d'événements optionnelles
QThread constitue la base de tout le contrôle des threads dans Qt. Chaque instance de ` QThread ` représente et contrôle un thread.
QThread Elle peut être instanciée directement ou sous-classée. L'instanciation d'une instance QThread fournit une boucle d'événements parallèle, permettant d'appeler les slots d'QObject s dans un thread secondaire. La sous-classification d'une instance QThread permet à l'application d'initialiser le nouveau thread avant de démarrer sa boucle d'événements, ou d'exécuter du code en parallèle sans boucle d'événements.
Consultez les exemples relatifs à ` QThread class reference ` et au multithreading pour découvrir comment utiliser ` QThread`.
QThreadPool et QRunnable : réutilisation des threads
La création et la destruction fréquentes de threads peuvent s’avérer coûteuses. Pour réduire cette surcharge, les threads existants peuvent être réutilisés pour de nouvelles tâches. Un ` QThreadPool ` est un ensemble de `QThreads` réutilisables.
Pour exécuter du code dans l’un des threads d’un QThreadPool, réimplémentez QRunnable::run() et instanciez la sous-classe QRunnable. Utilisez QThreadPool::start() pour placer l’ QRunnable dans la file d’attente d’exécution de l’ QThreadPool. Lorsqu’un thread devient disponible, le code contenu dans QRunnable::run() s’exécutera dans ce thread.
Chaque application Qt dispose d’un pool de threads global, accessible via QThreadPool::globalInstance(). Ce pool de threads global maintient automatiquement un nombre optimal de threads en fonction du nombre de cœurs du processeur. Cependant, il est possible de créer et de gérer explicitement un pool de threads distinct QThreadPool.
Qt Concurrent: Utilisation d’une API de haut niveau
Le Qt Concurrent module fournit des fonctions de haut niveau qui gèrent certains modèles courants de calcul parallèle : map, filter et reduce. Contrairement à l’utilisation de ` QThread ` et ` QRunnable`, ces fonctions ne nécessitent jamais le recours à des primitives de multithreading de bas niveau telles que les mutex ou les sémaphores. Au lieu de cela, elles renvoient un objet ` QFuture ` qui permet de récupérer les résultats des fonctions lorsqu’ils sont prêts. ` QFuture ` peut également être utilisé pour interroger la progression du calcul et pour mettre en pause, reprendre ou annuler le calcul. Pour plus de commodité, ` QFutureWatcher ` permet d’interagir avec les ` QFuture` via des signaux et des slots.
Qt ConcurrentLes algorithmes `map`, `filter` et `reduce` répartissent automatiquement le calcul sur tous les cœurs de processeur disponibles ; ainsi, les applications écrites aujourd’hui continueront à s’adapter lorsqu’elles seront déployées ultérieurement sur un système doté d’un plus grand nombre de cœurs.
Ce module fournit également la fonction QtConcurrent::run(), qui permet d’exécuter n’importe quelle fonction dans un autre thread. Cependant, QtConcurrent::run() ne prend en charge qu’un sous-ensemble des fonctionnalités disponibles pour les fonctions map, filter et reduce. La méthode ` QFuture ` peut être utilisée pour récupérer la valeur de retour de la fonction et pour vérifier si le thread est en cours d’exécution. Cependant, un appel à ` QtConcurrent::run()` n’utilise qu’un seul thread, ne peut être ni mis en pause, ni repris, ni annulé, et il est impossible d’interroger sa progression.
Consultez la Qt Concurrent documentation du module pour plus de détails sur les différentes fonctions.
WorkerScript : gestion des threads en QML
Le type QML ` WorkerScript ` permet d’exécuter du code JavaScript en parallèle avec le thread de l’interface graphique.
Chaque instance d’ WorkerScript peut être associée à un script .js. Lorsque WorkerScript.sendMessage() est appelé, le script s’exécute dans un thread distinct (et un QML context distinct). Une fois l’exécution du script terminée, celui-ci peut renvoyer une réponse au thread de l’interface graphique, ce qui déclenchera le gestionnaire de signal WorkerScript.onMessage().
L’utilisation d’un « WorkerScript » s’apparente à celle d’un « worker » QObject qui aurait été déplacé vers un autre thread. Les données sont transférées entre les threads via des signaux.
Consultez la documentation relative à l’ WorkerScript pour plus de détails sur la manière d’implémenter le script, ainsi que pour obtenir la liste des types de données pouvant être transmis entre les threads.
Choisir une approche adaptée
Comme illustré ci-dessus, Qt propose différentes solutions pour développer des applications multithread. La solution la plus adaptée à une application donnée dépend de l’objectif du nouveau thread et de sa durée de vie. Vous trouverez ci-dessous une comparaison des technologies de multithreading de Qt, suivie de solutions recommandées pour quelques exemples de cas d’utilisation.
Comparaison des solutions
| Fonctionnalité | QThread | QRunnable et QThreadPool | QtConcurrent::run() | Qt Concurrent (Map, Filter, Reduce) | WorkerScript |
|---|---|---|---|---|---|
| Langage | C++ | C++ | C++ | C++ | QML |
| La priorité d'un thread peut être spécifiée | Oui | Oui | |||
| Un thread peut exécuter une boucle d'événements | Oui | ||||
| Le thread peut recevoir des mises à jour de données via des signaux | Oui (reçues par un worker QObject) | Oui (reçues par l'WorkerScript) | |||
| Un thread peut être contrôlé à l'aide de signaux | Oui (reçues par QThread) | Oui (reçues par QFutureWatcher) | |||
| Le thread peut être surveillé via un QFuture | En partie | Oui | |||
| Fonctionnalité intégrée permettant de mettre en pause, de reprendre ou d’annuler | Oui |
Exemples d'utilisation
| Durée de vie du thread | Opération | Solution |
|---|---|---|
| Un seul appel | Exécuter une nouvelle fonction linéaire dans un autre thread, avec, si nécessaire, des mises à jour sur la progression pendant l'exécution. | Qt propose différentes solutions :
|
| Un seul appel | Exécutez une fonction existante dans un autre thread et récupérez sa valeur de retour. | Exécutez la fonction à l’aide de QtConcurrent::run(). Configurez un QFutureWatcher pour qu’il émette le signal finished() lorsque la fonction est revenue, puis appelez QFutureWatcher::result() pour récupérer la valeur de retour de la fonction. |
| Un seul appel | Effectuez une opération sur tous les éléments d’un conteneur, en utilisant tous les cœurs disponibles. Par exemple, générez des vignettes à partir d’une liste d’images. | Utilisez la fonction ` QtConcurrent::filter()` de ` Qt Concurrent` pour sélectionner les éléments du conteneur, et la fonction ` QtConcurrent::map()` pour appliquer une opération à chaque élément. Pour regrouper la sortie en un seul résultat, utilisez plutôt ` QtConcurrent::filteredReduced()` et ` QtConcurrent::mappedReduced()`. |
| Un seul appel / Permanent | Effectuez un calcul long dans une application QML pure, puis mettez à jour l’interface graphique lorsque les résultats sont prêts. | Placez le code de calcul dans un script « .js » et associez-le à une instance « WorkerScript ». Appelez ` WorkerScript.sendMessage()` pour lancer le calcul dans un nouveau thread. Laissez le script appeler également `sendMessage()` afin de renvoyer le résultat au thread de l’interface graphique. Traitez le résultat dans ` onMessage ` et mettez à jour l’interface graphique à cet endroit. |
| Permanent | Disposez d’un objet résidant dans un autre thread, capable d’effectuer différentes tâches à la demande et/ou de recevoir de nouvelles données à traiter. | Sous-classez un ` QObject ` pour créer un « worker ». Instanciez cet objet « worker » ainsi qu’un ` QThread`. Déplacez le « worker » vers le nouveau thread. Envoyez des commandes ou des données à l’objet « worker » via des connexions signal-slot en file d’attente. |
| Permanent | Exécutez de manière répétée une opération coûteuse dans un autre thread, où ce dernier n’a pas besoin de recevoir de signaux ni d’événements. | Écrivez la boucle infinie directement dans une réimplémentation de ` QThread::run()`. Lancez le thread sans boucle d’événements. Laissez le thread émettre des signaux pour renvoyer des données au thread de l’interface graphique. |
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.