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 :

Conflit XLib : Unknown request in queue while dequeuing [QThread]


Sujet :

Multithreading

  1. #1
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut Conflit XLib : Unknown request in queue while dequeuing
    Bonjour,

    Je suis sur Ubuntu 11 et utilise QT4.7.3 avec QTCreator 2.2.1.
    Dans une application multi-thread utilisant une classe héritant de QThread, et affichant des fenêtres OpenCV, j'obtiens parfois cette erreur qui interrompt mon programme :

    [xcb] Unknown request in queue while dequeuing
    [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
    [xcb] Aborting, sorry about that.
    Après quelques recherches, il semblerait que lorsque des threads sont susceptibles d'utiliser des éléments de XLib, il faille appeler avant toute création de thread, XInitthread();

    J'ai donc ajouté ceci à mon programme dans le main :

    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
     
    ...
    #include <X11/Xlib.h>
    ...
     
     
    /** @function main */
    int main( int argc, const char** argv )
    {
     
        XInitThreads();
     
        // Do something
     
        return  0;
    }
    Or, ce nouvel include me provoque une bonne cinquantaine d'erreurs de ce type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /usr/include/qt4/QtCore/qtextstream.h:60: error: #error qtextstream.h must be included before any header file that defines Status
    /usr/include/opencv2/flann/dist.h:82: error: expected unqualified-id before numeric constant
    Après d'autres recherces, il semblerait que le souci apparaisse à cause des classes True et False dans dist.h, qui seraient en conflit avec d'autres classes du même nom quelque part.

    Dans dist.h il y a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class True
    {
    };
     
    class False
    {
    };
    Et à partir de là je ne sais plus comment faire pour régler ce problème, qui semble être récurrent sous Ubuntu 11.

    Avez-vous quelques idées ?

    Merci d'avance et bonne journée

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968

  3. #3
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Très bien je vais passer par de signaux et de slots. Je pensais que l'utilisation de mutex suffirait.
    Je vais essayer ça et reviens mettre le post en "résolu" si c'est le cas.
    Qt garantit que l'exécution de slots est thread-safe n'est-ce pas ?

    Merci et bonne journée.

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Si son appel dépend d'un connect oui. (faut laisser le mode de conection par défaut)

    Sinon, c'est une fonction comme une autre avec les même problème de multithread


    Citation Envoyé par Shargat Voir le message
    Très bien je vais passer par de signaux et de slots. Je pensais que l'utilisation de mutex suffirait.
    Je vais essayer ça et reviens mettre le post en "résolu" si c'est le cas.
    Qt garantit que l'exécution de slots est thread-safe n'est-ce pas ?

    Merci et bonne journée.

  5. #5
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Merci.

    Après avoir implémenté les signaux et slots pour qu'un seul thread gère l'affichage d'éléments graphiques de XLib, j'obtiens un comportement aléatoire.

    Parfois, le programme tourne, parfois l'erreur suivante apparait après qu'un thread soit lancé:

    Fatal IO error 11 (Resource temporarily unavailable) on X server :0.
    et parfois je revois cette erreur :

    [xcb] Unknown sequence number while processing queue
    [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
    [xcb] Aborting, sorry about that.
    test3_FaceThread_algo: ../../src/xcb_io.c:273: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
    Je suis un peu paumé. Je vais regarder un peu d'où peuvent venir ces erreurs.
    Ca semble rappeler l'erreur initiale de ce post, car liée au système graphique X11. Mon programme utilise OpenCV et affiche différentes frames. L'affichage des frames est actuellement assurée par un seul objet singleton encapsulé dans un QThread réveillé par les signaux que lui envoient les différents autres threads pour qu'il affiche une donnée.

    Merci pour ton aide en tout cas.

    EDIT :

    Bon il semblerait que je fasse tout de travers. Désolé mais je ne suis pas familier de la programmation multi-thread.
    Ci-dessous, je crée un thread et son objet encapsulé :

    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
     
    class Displayer : public QObject
    {
        Q_OBJECT
     
    public slots:
        void displayMat(Mat*, QString);              // Slot displaying the Mat image
     
    };
     
     
     
    class DisplayerThread : public QThread
    {
        Q_OBJECT
     
    protected:
        void run()
        {
            // Create internal object
            Displayer _displayer;
            // Connect input slots to output slots
            connect(this,SIGNAL( displayMat(Mat*, QString)),&_displayer,SLOT( displayMat(Mat*, QString)));
            // Run eventLoop
            exec();
        }
     
    signals:
        void displayMat(Mat*, QString);
    };
    Et ci-dessous le singleton qui encaspule ce thread (le thread doit être un singleton accessible dans le programme) :

    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
     
    class SingletonDisplayThread
    {
    private :
        SingletonDisplayThread();
     
    public :
        static DisplayerThread* getInstance() {
            if (_displayThread == NULL)
            {
                _displayThread =  new DisplayerThread();
                _displayThread->start();
            }
     
            return _displayThread;
        }
     
        static void kill ()
        {
            if (_displayThread != NULL)
            {
                _displayThread->exit();
               _displayThread->wait();
     
                delete _displayThread;
                _displayThread = NULL;
            }
        }
     
    private :
        static DisplayerThread* _displayThread;
    };
    DisplayerThread* SingletonDisplayThread::_displayThread = NULL;
    Et enfin, voici dans mon thread principal comment je lance tout ce petit monde :

    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
     
                for (int i = 0; i < faces.size(); i++)
                {
                            /// We create and run a new FaceThread
                            QThread* thread = new QThread;
                            FaceTracker* tracker = new FaceTracker(currentFace, frame, &_captureV);
                            tracker->moveToThread(thread);
                            QObject::connect(thread, SIGNAL(started()), tracker, SLOT(process()));
                            QObject::connect(tracker, SIGNAL(finished()), thread, SLOT(terminate()));
                            QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
                            QObject::connect(tracker, SIGNAL(askDisplayMat(Mat*,QString)), SingletonDisplayThread::getInstance(), SIGNAL(displayMat(Mat*,QString)));
                            thread->start();
                            tabThreads.push_back(thread);
          }
     
     
     /// We wait until all the tracker finish
                for(int j = 0;j < tabThreads.size(); j++)
                {
                     (QThread*)(tabThreads.at(j))->wait();
                }
    Outre les erreurs évoquées ci-dessus, lorsque le programme se lance correctement, les threads créés plus haut ( pas le singleton, les autres ) semblent ne jamais s'arrêter. Le programme reste bloqué dans la dernière boucle for, en attente de terminaison des threads. Pourtant je fais bien

    à la fin de l'exécution de ces threads.

    Qu'est-ce que je fais mal ? Je soupçonne le thread de ne pas recevoir le signal "finished" du tracker.

    Merci d'avance, j'ai passé 2 heures à tenter de déboguer ce code, sans succès.

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Il semble que tu est un problème entre les QObject et leurs association avec les threads. Mais je n'en suis pas sure. Tu semble avoir compris le principe.

    Qui t'affiche l'image?

    Pour qu'un slot s’exécute dans un thread, il faut que l'eventloop du thread soit lancée et qu'elle soit pas bloquée par une exécution quelconque.

    Peux tu expliquer un peu ce que font tes threads?

    En regardant ton code, je me demande si tu ne devrais pas plutôt utiliser les QtConcurrent :
    http://qt-project.org/doc/qt-4.8/qtconcurrentmap.html

    Et avec un QFutureWatcher, tu pourra même éviter d'attendre la fin du calcul.
    http://qt-project.org/doc/qt-4.8/qfuturewatcher.html

    Le gros avantage c'est qu'il va utiliser un nombre de thread cohérent avec ta machine et que tu peux utiliser les thread de manière implicite.

  7. #7
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Bonjour,

    Je suis en train de regarder la doc de QtConcurrent et QFutureWatcher.
    Après cela, je vais simplifier mon programme pour isoler le problème au maximum.

    Mon programme utilise OpenCV pour détecter et traquer des visages sur une vidéo.
    L'algo est simple en soit :

    1. Lire une première frame
    2. Détecter des visages
    3. Pour chaque visage détecté lancer un thread qui va traquer ce visage dans les frames suivantes et afficher la frame en appelant le thread displayer


    En parallèle, un autre thread est créé par le thread principal, c'est le thread displayer qui est chargé d'attendre qu'un signal le réveille pour afficher dans une fenetre certaines informations ( le but étant de contourner le fait que X11 ne soit pas thread-safe ).

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    OpenCV est thread safe?


    Citation Envoyé par Shargat Voir le message
    En parallèle, un autre thread est créé par le thread principal, c'est le thread displayer qui est chargé d'attendre qu'un signal le réveille pour afficher dans une fenetre certaines informations ( le but étant de contourner le fait que X11 ne soit pas thread-safe ).
    pourquoi ne pas utiliser le thread principale???

  9. #9
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Parce que j'ai besoin qu'il soit réveillé par des signaux pour exécuter des slots. Or je ne vois pas comment ajouter des slots au thread principal, qui selon moi n'hérite pas de QObject...

    Au passage : après simplification maximale du code, je confirme que les threads créés envoient bien le signal askDisplyMat(), mais le thread displayer ne semble pas les recevoir.

    EDIT
    Je remarque que si j'exécute mon objet dans le thread principal (je ne fais pas le moveToThread), alors le signal est bien reçu par le displayer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     QThread* thread = new QThread;
            MyObject* obj = new MyObject();
           // obj->moveToThread(thread);   On supprime cette ligne
            // QObject::connect(thread, SIGNAL(started()), obj, SLOT(process()));
           // QObject::connect(obj, SIGNAL(finished()), thread, SLOT(quit()));
            //QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
            QObject::connect(obj, SIGNAL(askDisplayMat(int)), SingletonDisplayThread::getInstance(), SIGNAL(askDisplayMat(int)));
           obj->process();
            // thread->start();
            // tabThreads.push_back(thread);
    Les connexions ne sont-elles valables que dans le thread qui les établi ?

  10. #10
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Shargat Voir le message
    Parce que j'ai besoin qu'il soit réveillé par des signaux pour exécuter des slots. Or je ne vois pas comment ajouter des slots au thread principal, qui selon moi n'hérite pas de QObject...
    Imagine plutôt les QThread comme des espaces d’exécutions et les QObject comme des module.
    Le thread principale est l'espace d’exécution principale spécifique à l'affichage. Quand tu créé un QObject, QWidget, ... dans ce thread, il s'associé au thread principale. Le moveToThread ne sert qu'à déplacer ces modules(QObject) dans d'autre espace d’exécution (QThread).

    Tu n'utilise pas la partie GUI de Qt?

  11. #11
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Oui pardon. J'ai bien compris qu'un Thread encapsule un objet qui détient les fonctionnalités recherchées.
    Un thread a des signaux mais pas de slots.

    Je n'utilise pas la partie GUI de Qt. J'affiche des fenêtres via OpenCV.

    Mon programme simplifié revient à cela :

    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
     
        vector<QThread*> tabThreads;
     
        for (int i = 0; i < 2; i++)
        {
            /// We create and run a new Thread
            QThread* thread = new QThread;
            MyObject* obj = new MyObject();
            obj->moveToThread(thread);
            QObject::connect(thread, SIGNAL(started()), obj, SLOT(process()));
            QObject::connect(this, SIGNAL(askDisplayMat(int)), SingletonDisplayThread::getInstance(), SIGNAL(askDisplayMat(int)));
            QObject::connect(obj, SIGNAL(finished()), thread, SLOT(quit()));
            QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
            thread->start();
            tabThreads.push_back(thread);
        }
     
     
        /// We wait until all the threads finish
        for(int j = 0;j < tabThreads.size(); j++)
        {
            cout << "attente thread" << endl;
            (QThread*)(tabThreads.at(j))->wait();
            cout << "done" << endl;
        }
        /// Empty the tabThreead
        tabThreads.clear();
     
     
        SingletonDisplayThread::kill();
    Les threads sont bien lancés, les objets encaspulés s'exécutent, mais tout signal émis par ces objets n'est jamais catché (ni le signal askDisplayMat destiné au singleton, ni le signal finished() destiné au thread )
    Je précise que si j'émets un signal askDisplayMat() depuis le thread principal, alors le singleton le réceptionne correctement.

  12. #12
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    quand lance tu l'eventloop principale??
    QCoreApplication::exec()

  13. #13
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Et bien là-dessus je ne suis pas très sûr.

    J'ai dû rajouter

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QApplication app(argc, argv);
    au tout début de mon programme, car sinon j'avais un message d'erreur sur l'utilisation des signaux/slots. Mais je n'appelle jamais app.exec() car je n'en ai jamais besoin... Basiquement, j'ai juste ajouté cette ligne pour faire taire le compilateur et pouvoir exécuter des signaux/slots.
    Voici le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    /** @function main */
    int main( int argc, char* argv[] )
    {
        QApplication app(argc, argv);
     
        // Run the code above
        ProcessProg p;
        p.run();
     
        return 0;
    }
    C'est mal ? L'ajout de return app.exec(); ne change rien, si ce n'est que mon programme ne s'arrête jamais ( ceci dit, il s'arrête déjà jamais puisque les theads ne sont pas terminés, puisqu'ils ne reçoivent pas le signal "finished" de obj )

  14. #14
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Shargat Voir le message
    C'est mal ?
    Ben c'est pour cela que tes signaux ne sont pas catché comme tu dit

    Tes QThread sont des modules qui s’exécutent dans le thread principale. Donc pour que leurs slot s'éxécute il faut une eventloop qui tourne.

    Un QThread ne sert que d'interface à un thread système.

    A mon avis il faut mieux que ton displayer s'éxécute dans le thread principale.

  15. #15
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Merci pour ton assiduité ^^ Je remarque tout juste que tu es l'auteur de la FAQ dont je m'inspire. Merci pour les éclaircissements qu'elle apporte au passage, car on trouve tout et nimporte quoi sur l'utilisation des QThreads.

    Il y a une chose que je comprend mal, c'est l'utilisation de app.exec(). Car mon application n'utilise pas de GUI et n'attend pas d'évènements provenant de GUI. Si je lance app.exec(), j'entre dans une boucle qui attend un évènement qui ne viendra jamais. Or moi je veux que mon programme continue à s'exécuter automatiquement, même après app.exec(). Je voudrais le rendre non bloquant...

    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
     
    int main( int argc, char* argv[] )
    {
        QApplication app(argc, argv);
     
        // Se bloque ici
        app.exec();
     
         // Devrait continuer sans attendre d'évènements
        ProcessProg p;
     
        p.run();
     
        return 0;
    }
    EDIT :
    Selon ton conseil, le displayer est désormais exécuté dans le thread principal.

  16. #16
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    app.exec() exécute l'eventloop du thread principale. Regarde le code de QThread, c'est ce qu'il fait aussi par défaut mais dans un thread secondaire.
    en générale un Code qt est comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main( int argc, char* argv[] )
    {
        QApplication app(argc, argv);
     
         //création des objets
        ProcessProg p;
       /*...*/
     
       // exécute l'eventloop
        return app.exec();
    }
    Ce qu'il te faudrait c'est un QObject qui encapsule le tous avec des signal/slot.

    Qt est un framework évènementiel et donc faut plutôt penser en méthode asynchrone.

    Quand tu fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (QThread*)(tabThreads.at(j))->wait();
    tu bloque l 'eventloop. faudrait plutôt un slot qui regarde si tout les threads sont en éxécution quand un signal finished est émit.

  17. #17
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Tu veux dire qu'il faudrait que je lance l'exécution de mon code via un slot après un délai imparti, pour laisser le temps de l'appel app.exec() ?

    En fait, ce qui me perturbe, c'est que l'appel app.exec() se fasse à la fin du pogramme, alors que mon code s'exécute avant.
    ( D'ailleurs je viens de voir qu'il vaut mieux pour moi utiliser QCoreApplication plutôt que sa classe héritée QApplication )

    Quand tu fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (QThread*)(tabThreads.at(j))->wait();
    tu bloque l 'eventloop. faudrait plutôt un slot qui regarde si tout les threads sont en éxécution quand un signal finished est émit
    Oui ça je sais, mais c'est volontaire. Pour l'instant je ne m'en préoccupe pas.

    EDIT
    J'ai modifié mon programme comme ceci, en ajoutant un Timer pour que le code s'exécute après l'appel à exec() . Le comportemant est similaire. Les signaux des MyObject ne sont jamais reçu par le Displayer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int main( int argc, char* argv[] )
    {
        QCoreApplication app(argc, argv);
     
        ProcessProg p;
     
        QTimer::singleShot(2000, &p, SLOT(run()));
     
     
        return  app.exec();;
    }
    et le slot run() de PRocessProg :

    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
    void ProcessProg::run(){
     
        Displayer* d = new Displayer();
        vector<QThread*> tabThreads;
     
        QObject::connect(this, SIGNAL(askDisplayMat(int)),d, SLOT(displayMat(int)));
        emit askDisplayMat(1); // This emit works, the signal is catched by the displayer
     
        for (int i = 0; i < 2; i++)
        {
            /// We create and run a new Thread
            QThread* thread = new QThread;
            MyObject* obj = new MyObject();
            obj->moveToThread(thread);
            QObject::connect(thread, SIGNAL(started()), obj, SLOT(process()));
            QObject::connect(obj, SIGNAL(askDisplayMat(int)),d, SLOT(displayMat(int)));
            QObject::connect(obj, SIGNAL(finished()), thread, SLOT(quit()));
            QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
            thread->start();
            tabThreads.push_back(thread);
        }
     
     
        /// We wait until all the tracker finish
        for(int j = 0;j < tabThreads.size(); j++)
        {
            (QThread*)(tabThreads.at(j))->wait();
        }
        /// Empty the tabThreead
        tabThreads.clear();
     
        exit(0);
    }
    et enfin l'exécution des MyObject :

    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
     
    void MyObject::process()
    {
        cout << "dans MyObject::process()" << endl;
     
        sleep(1);
     
        for ( int i = 0; i < 10; i++ )
        {
            emit askDisplayMat(i);
            sleep(1);
        }
     
        cout << "finished emitted" << endl;
        emit finished();
    }

  18. #18
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Shargat Voir le message
    Tu veux dire qu'il faudrait que je lance l'exécution de mon code via un slot après un délai imparti, pour laisser le temps de l'appel app.exec() ?
    vue que tu utilise des thread, non. Mais tu peux très bien utiliser
    http://qt-project.org/doc/qt-4.8/qtimer.html#singleShot
    ou
    http://qt-project.org/doc/qt-4.8/qme...od.html#invoke

    pour qu'un slot se lance aprés le lancement de l'eventloop.

    En fait, ce qui me perturbe, c'est que l'appel app.exec() se fasse à la fin du pogramme, alors que mon code s'exécute avant.
    Non en parallèle t'es en multithread. Le début du code ne sert en gros qu'à lancer tes thread et y ajouter des modules d’exécution.

    ( D'ailleurs je viens de voir qu'il vaut mieux pour moi utiliser QCoreApplication plutôt que sa classe héritée QApplication )
    Tu peux intégrer l'affichage OpenCV dans Qt, donc peut être garder QApplication pour le futur?


    Oui ça je sais, mais c'est volontaire. Pour l'instant je ne m'en préoccupe pas.
    Alors enlève le et utilise exec

    Je ne sais pas trop quels sont les points qui te posent problèmes.

    Je te conseil cette article : http://qt-labs.developpez.com/thread...ans-maux-tete/

  19. #19
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Le comportemant est similaire. Les signaux des MyObject ne sont jamais reçu par le Displayer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     for(int j = 0;j < tabThreads.size(); j++)
        {
            (QThread*)(tabThreads.at(j))->wait();
        }
    wait est bloquant => bloque l'eventloop => les slots attendent leurs tour pour être exécuté.

  20. #20
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2008
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2008
    Messages : 138
    Points : 70
    Points
    70
    Par défaut
    Très bien, merci beaucoup. Je comprend mieux à présent.
    Je me bornais à penser que le wait() pouvait être réveillé par un signal.

    Quant au singleShot, ça semble effectivement être la solution.
    Encore merci pour ton aide. Je clique sur "résolu"

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 10
    Dernier message: 07/10/2010, 17h56
  2. Erreur "Caught exception while handling request"
    Par URIOS dans le forum Web & réseau
    Réponses: 13
    Dernier message: 31/03/2009, 21h28
  3. [MySQL] conflit entre deux fonction while
    Par guillaumeIOB dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 04/12/2006, 12h56
  4. [MySQL] Conflit entre deux fonction WHILE
    Par guillaumeIOB dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 28/11/2006, 18h15
  5. [XSLT] Error while parsing XSL file (unknown protocol: e)
    Par SONY30 dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 26/09/2006, 13h58

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