IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Multithreading Discussion :

Exécution en boucle [QThread]


Sujet :

Multithreading

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Exécution en boucle
    Bonjour,

    Je développe actuellement un logiciel de prise de mesure et j'ai un soucis pour l'exécution continue du thread.

    Mon logiciel est construit selon une architecture multi-threadée. Principalement, il dispose d'un thread principal (contenant l'IHM) et d'un thread de mesure.

    Constructeur du thread principal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Manager::Manager(int argv, char* argc[])
    {
         QApplication app(arv, argc);
         m_mesureInterface = new MeasureInterface();
         m_mainGUI = new ClasseHeritantMainWindow();
     
         QObject::connect(m_mainGUI, SIGNAL(startSignal()), m_mesureInterface, SLOT(start()));
         QObject::connect(m_mainGUI, SIGNAL(stopSignal()), m_mesureInterface, SLOT(stop()));
     
         m_mainGUI->show();
         app.exec();
    Et voici une partie du code de la classe de mesure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    MeasureInterface::MeasureInterface()
    {
         moveToThread(&m_tread);
         m_thread.start();
         QObject::connect(this, SIGNAL(initiateSignal()), this, SLOT(initiate()));
         QObject::connect(this, SIGNAL(nextStep()), this, SLOT(execute()));
         emit initiateSignal();
    }
     
    void MeasureInterface::start()
    {
         m_continue = true;
         execute();
    }
     
    void MeasureInterface::stop()
    {
         m_continue = false;
    }
     
    void MeasureInterface::execute()
    {
         //   Pilotage de l'appareil pour prise de mesure
     
         emit transmitResult(Result res);
     
         if(m_continue)
              emit nextStep();
    }
    Le but de tout ceci est que le thread de mesure doit tourner en continu de façon indépendante, sans jamais être dérangé par l'exécution des autres threads du logiciel. Ma toute première idée avait été une boucle while dans la fonction execute(), mais bien entendu, ce n'est pas possible puisque cela bloque la boucle évènementielle.

    Une autre version, celle actuellement utilisée, envoie au thread principal un signal de résultat, et dès que ce signal est reçu, le thread principal envoie un signal pour rappeler la fonction execute(). Cela fonctionnait bien, mais me pose un problème : si le thread principal est déjà occupé sur une opération longue, le signal est mis en attente et cela bloque le fonctionnement du thread de mesure.

    J'ai donc tenté la solution du code écrit plus haut. A priori, cela fonctionne, mais lorsque j'essaie de stopper l'exécution (par l'envoi du signal stop), tout plante. Ce fonctionnement partiel me laisse penser que l'idée mais est bonne mais que je m'y prend mal.

    Si vous savez ce qui ne colle pas, ou même si vous avez une autre façon de faire à proposer, cela m'aiderait bien.

    Cordialement.
    Dernière modification par Invité ; 06/03/2013 à 17h19.

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut
    Citation Envoyé par Lelfic Voir le message
    Ma toute première idée avait été une boucle while dans la fonction execute(), mais bien entendu, ce n'est pas possible puisque cela bloque la boucle évènementielle.
    Pourquoi es ce que bloquer l'eventloop du thread te derange?

  3. #3
    Invité
    Invité(e)
    Par défaut
    Si je bloque l'eventloop, les signaux ne sont plus reçus par le thread, et je ne peux donc plus interrompre ma boucle while.

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Lelfic Voir le message
    Si je bloque l'eventloop, les signaux ne sont plus reçus par le thread, et je ne peux donc plus interrompre ma boucle while.
    oui et non ^^
    as tu fait un tour dans la FAQ?
    Ce qui faut bien comprendre c'est qui est exécute par qui. Ton thread doit lancer une eventloop unique si un QObject est associé a ton thread.
    Dans ton cas tu ne semble pas avoir besoin de l'eventloop. Il y as une subtilité important a comprendre : un QThread interface un thread mais n'est pas executé dans ce thread. Tu peux donc faire une boucle while(test) dans le run et un slot dans le QTHread qui mettra test faux pour finaliser la boucle while.

    Si tu as besoin des signal/slot dans le thread, il faut mieux créer des QObject et faire des movetothread. Depuis 4.7 ou 4.6 tu n'est pas obligé de reimplementer QThread. Par defaut il lance une eventloop dans un thread.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Nulle part dans mon logiciel je n'hérite QThread, j'utilise toujours, justement, la méthode du moveToThread() indiquée dans le sujet en tête du forum.

    je n'utilise donc pas la fonction run() mais la fonction execute() de mon cru qui est un slot. Je crois que quelque chose m'échappe.

    Mon object MeasureInterface possède un QThread (natif, pas hérité). Le constructeur de mon objet, comme indiqué dans le premier post, apelle moveToThread() qui devrait, si j'a ibien compris, faire en sorte que les slots de l'objet s'exécutent dans ce QThread lorsqu'ils sont appellés par des signaux. Le slot en question, c'est la fonction execute(), qui est appelée une première par un signal venant du thread principal de l'application, et qui ensuite s'appelle elle même par son propre signal. J'ai tout bon jusque là ?

    Ensuite, l'objet comporte un autre slot servant à interrompre l'envoi du signal qui boucle sur execute(). C'est lorsque j'appelle cet autre slot que mon application plante.

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Lelfic Voir le message
    Mon object MeasureInterface possède un QThread (natif, pas hérité). Le constructeur de mon objet, comme indiqué dans le premier post, apelle moveToThread() qui devrait, si j'a ibien compris, faire en sorte que les slots de l'objet s'exécutent dans ce QThread lorsqu'ils sont appellés par des signaux.
    Yep, mais uniquement si le signal est emit par un autre thread. Sinon cela appelle directement le slot(sauf si tu as changé le mode de connection)

    Le slot en question, c'est la fonction execute(), qui est appelée une première par un signal venant du thread principal de l'application, et qui ensuite s'appelle elle même par son propre signal. J'ai tout bon jusque là ?
    Le premier execute sera ok, mais les suivant vont produire un appel récursive a ta fonction => boom tu va exploser la pile d'appelle ^^

    Pour faire un boucle, tu peux aussi te créer un timer avec un timeout de 0 et reimplementer TimerEvent.

    De tête ca donne un truc comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    class monObjet : public Object
    {
    Q_OBJECT
    int timerId;
     
    public :
    	monObjet():timerId(-1){}
     
    public slots :
     
    	void demarerMesure()
    	{
    	if(timerId ==-1)
    		timerId = startTimer(0);
    	}
    	void stopperMesure()
    	{
    		if(timerId !=-1)
    		{
    			killtimer(timerId);
    			timerId = -1;
    		}
    	}
     
    protected :
    	 void timerEvent ( QTimerEvent * event )
    	 {
    		 if(event->timerId ()  == timerId)
    		 {
    		 //mesure
    		 }
    	 }
     
    };
    Pour l'intervalle de 0 regarde la doc ici : http://qt-project.org/doc/qt-4.8/qob...tml#startTimer

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Exécuter une boucle à une fréquence donnée.
    Par xoomed dans le forum VB 6 et antérieur
    Réponses: 12
    Dernier message: 05/02/2011, 02h31
  2. Lenteur d'exécution (grande boucle accédant à une dll)
    Par kattig dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 11/09/2010, 21h33
  3. modifier/choisir ordre d'exécution de boucles
    Par blable dans le forum LabVIEW
    Réponses: 1
    Dernier message: 14/06/2010, 21h52
  4. Exécuter une boucle tant que le programme tourne
    Par maxetx dans le forum Threads & Processus
    Réponses: 4
    Dernier message: 14/04/2009, 12h40
  5. exécution de boucle de macro
    Par magicfrom dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 23/04/2008, 16h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo