Qt : Traiter une liste de façon non bloquante

Pour qu’une interface graphique reste fluide aux yeux de l’utilisateur, le thread qui la gère ne doit jamais être interrompu plus d’une poignée de millisecondes. Or le parcours d’une liste avec une boucle est de nature à bloquer ce thread. Voici comment parcourir une liste sans bloquer le thread.

Soit l’algorithme suivant :

L’exécution complète de cet algorithme durera, selon l’estimation faite en commentaire, entre 50 et 90 secondes.

Si l’application ne contient que le thread principal, c’est-à-dire le même que celui de l’interface graphique, l’utilisateur ne pourra pas agir sur la fenêtre pendant 50 à 90 secondes.

Pire, l’utilisateur ne verra même la barre de progression évoluer, elle passera directement de vide à remplie.

Une des solutions constiterait à effectuer cette boucle dans un thread… mais Qt offre des mécanismes beaucoup plus souples, ce serait une mauvaise réponse à un problème conceptuel simple. Dans un prochain article je vous expliquerai pourquoi je ne suis pas partisan d’utiliser les threads pour autre chose que la parallélisation.

Boucle asynchrone

Une solution plus adaptée à la conception de Qt est l’usage de la boucle asynchrone, au lieu de boucler, nous allons faire des appels successifs à une fonction d’itération. Biensûr ces appels passeront par la run-loop.

L’avantage de cette solution est que les itérations effectuées sur la run-loop seront effectuées dans le respect des appels de fonction liés à l’interface graphique.

En effet, l’appel ui->progressBar->setValue(iteration) induit une mise à jour de l’interface graphique par un appel à la run-loop. La run-loop contient un très grand nombre d’appels de fonctions liés à l’interface graphique, que vous ne soupçonnez même pas.

En ajoutant des appels à une fonction d’itération passant par la run loop, vous laissez s’exécuter les fonctions liées à l’interface graphique, puis la run-loop exécutera l’appel la fonction d’itération.

Vous vous imaginez que par conséquent l’itération sera plus longue puisqu’elle sera différée et que vous ne pouvez pas savoir quand elle le sera. Pour le second point je suis d’accord, en revanche l’expérience prouve que l’itération sera en réalité moins longue.

La raison est facile à comprendre : le fait de bloquer l’interface graphique et de boucler longuement sur une liste surcharge le processeur. Cela ralentit l’application mais aussi tout le système (selon la priorité des processus). Si vous allouez de la mémoire dans votre itération, l’activité mémoire augmentera et, ce faisant, vous encouragez le système à swapper, ce qui le ralentira.

Pour coder ce type de boucle, il existe plusieurs méthodes, je vous propose celle que j’utilise :

Cette façon de procéder, en plus de vous permettre de conserver la fluidité de votre interface graphique, vous oblige à concevoir le reste de votre application de façon asynchrone car pour connaître la fin du parcours de la liste il faut être capable de recevoir un signal.

Il est important de noter deux choses :

  1. il doit exister au moins un thread dans l’application. Vous devez donc appeler la fonction exec() de QApplication.
  2. la fonction appelée doit elle aussi être conçue selon le même modèle non-bloquant. Si besoin il faudra découper la fonction appelée en autant d’appels sur la run-loop et récupérer un signal en fin de traitement.

Voici comment procéder :

Partagez cet article !

Abonnez-vous à notre newsletter !

Si vous souhaitez être notifié lorsqu'un nouvel article est publié, abonnez-vous à notre newsletter et vous recevrez un email dès qu'un article sera publié.

Articles similaires

Qt : distribuer ses appli... La distribution d’une application est une étape importante de la vie d’une application, elle nécessite d’être pensée très tôt dans la conception. Cette série d’articles présente les
Qt : l’influence du... Lorsqu’on développe une application mutli-plateformes il est important de se poser la question des performances sur les plateformes ciblées. A machine égale, selon le compilateur utilisé les
Qt : pourquoi et quand ut... La gestion des threads dans Qt est simple mais elle mérite quelques explications car elle engendre souvent des problèmes conceptuels chez les développeurs peu expérimentés en Qt.
Qt : comment implanter un... Il existe plusieurs façons d’implanter des threads dans son application Qt.  Voici la méthode que je préconise. Partagez cet article ! Abonnez-vous à notre newsletter ! Si
Adopter les flux tirés d... Nous abordons un des points essentiels de l’architecture réseau et applicative efficace et économe : les flux tirés. Partagez cet article ! Abonnez-vous à notre newsletter !
Utiliser la technique du ... Le lazy-loading, ou chargement paresseux en français, est une réponse simple à la question simple “pourquoi charger plus de données que nous ne pouvons en afficher ?”.
Livre Maîtrisez Qt 5 ... La seconde édition du livre de Tristan Israël, Maîtrisez Qt 5 – Développement d’applications professionnelles, est parue. Vous pouvez le découvrir sur le site des éditions ENI.
Apprendre à développer ... Une de mes activités est la formation professionnelle à la conception et à la programmation d’applications avec Qt. J’envisage aujourd’hui de créer un MOOC payant pour partager
Qt : Traiter une liste de... Pour qu’une interface graphique reste fluide aux yeux de l’utilisateur, le thread qui la gère ne doit jamais être interrompu plus d’une poignée de millisecondes. Or le

Laisser une réponse

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *