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 :

Un moveToThread() rebelle [QThread]


Sujet :

Multithreading

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de VivienD
    Homme Profil pro
    Développeur logiciel
    Inscrit en
    Octobre 2009
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur logiciel
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 523
    Par défaut Un moveToThread() rebelle
    Bonsoir,

    J'ai créé un petit projet avec Qt Creator pour apprendre à manipuler les threads avec QThread. Ce projet qui n'a qu'un but ludique consiste à créer une sorte de métronome dans un thread différent du thread principal. Jusque là, rien d'anormal.

    Voici le fichier main.cpp
    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
    #include <QApplication>
     
    #include "mygui.h"
    #include "myclockwork.h"
     
    int main(int argc, char* argv[])
    {
        QApplication app(argc, argv);
     
        MyGui gui;
        MyClockwork clockwork;
        app.connect(&clockwork, SIGNAL(tick()), &gui, SLOT(tick()));
        app.connect(&app, SIGNAL(aboutToQuit()), &clockwork, SLOT(stop()));
     
        gui.show();
        clockwork.start();
     
        return app.exec();
    }
    Comme on peut le voir, le métronome (classe MyClockwork) possède deux slots publics, start() et stop(), ainsi qu'un signal tick(). Par ailleurs, le slot stop() est appelé quand l'application est sur le point de quitter; le problème réside là.
    Voici les fichiers liés à la classe du métronome:
    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
    #ifndef MYCLOCKWORK_H
    #define MYCLOCKWORK_H
     
    #include <QObject>
     
    #include <QApplication>
    #include <QThread>
    #include <QTimer>
     
    class MyClockwork : public QObject
    {
        Q_OBJECT
     
        public:
            MyClockwork(QObject* parent = 0);
            ~MyClockwork();
     
        public slots:
            void start();
            void stop();
     
        signals:
            void tick();
     
        private:
            QThread* m_thread;
            QTimer* m_timer;
     
        private slots:
            void timerFired();
    };
     
    #endif // MYCLOCKWORK_H
    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
    36
    37
    38
    39
    40
    #include "myclockwork.h"
     
    MyClockwork::MyClockwork(QObject* parent) :
        QObject     (parent)        ,
        m_thread    (new QThread)   ,
        m_timer     (new QTimer)
    {
        m_timer->setSingleShot(false);
    }
     
    MyClockwork::~MyClockwork()
    {
        delete m_timer;
        delete m_thread;
    }
     
    void MyClockwork::start()
    {
        m_timer->setInterval(1000);
        connect(m_timer, SIGNAL(timeout()), this, SLOT(timerFired()), Qt::DirectConnection);
        m_timer->start();
        m_timer->moveToThread(m_thread);
        m_thread->start();
    }
     
    void MyClockwork::stop()
    {
        if(m_thread->isRunning())
        {
            m_timer->moveToThread(QApplication::instance()->thread());
            m_thread->quit();
        }
        m_timer->stop();
        disconnect(m_timer, SIGNAL(timeout()), this, SLOT(timerFired()));
    }
     
    void MyClockwork::timerFired()
    {
        emit tick();
    }
    Le problème est que, lorsque je renvoie le minuteur m_timer dans le thread principal via la commande m_timer->moveToThread(QApplication::instance()->thread()), je reçois l'erreur suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QObject::moveToThread: Current thread (0x3779a8) is not the object's thread (0x7262a0).
    Cannot move to target thread (0x3779a8)
    En gros, l'application ne parvient pas à mettre l'objet QTimer dans le thread-cible.
    Pourquoi? Je ne sais pas; c'est pourquoi je sollicite votre aide.

    Merci d'avance.

    Adishatz!

    PS: Quand l'application est terminée, j'obtiens aussi cette erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QObject::killTimer: timers cannot be stopped from another thread

  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.
    C'est normal. Un QOBject (ici ton timer) est associé à un QThread.

    Au debut, le timer est associé au thread principale.
    Tu appel movetothread depuis le thread principal => le timer est associé à ton thread

    Au stop tu veux changer l'association du timer avec le thread principal => error. Cette fonction ne peut être exécuté que par le thread associé au timer. Tout comme le stop.

    http://doc.qt.digia.com/stable/qobje...l#moveToThread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Warning: This function is not thread-safe; the current thread must be same as the current thread affinity. In other words, this function can only "push" an object from the current thread to another thread, it cannot "pull" an object from any arbitrary thread to the current thread.
    c'est ce que tu fais

  3. #3
    Membre éclairé
    Avatar de VivienD
    Homme Profil pro
    Développeur logiciel
    Inscrit en
    Octobre 2009
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur logiciel
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 523
    Par défaut
    Je vois.

    J'avais créé cette fonction stop() non seulement pour arrêter proprement mon thread mais aussi pour ne pas avoir l'erreur ci-dessous.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QObject::killTimer: timers cannot be stopped from another thread
    Dois-je créer une classe spéciale pour déplacer le timer de l'intérieur du thread? Dois-je envisager une autre alternative?

  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 VivienD Voir le message
    Dois-je créer une classe spéciale pour déplacer le timer de l'intérieur du thread? Dois-je envisager une autre alternative?
    Ca depend de ce que tu veux faire...

    Que cherche tu à tester?

  5. #5
    Membre éclairé
    Avatar de VivienD
    Homme Profil pro
    Développeur logiciel
    Inscrit en
    Octobre 2009
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur logiciel
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 523
    Par défaut
    Je veux juste arrêter proprement mon minuteur pour ne plus avoir cette erreur.

  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 VivienD Voir le message
    Je veux juste arrêter proprement mon minuteur pour ne plus avoir cette erreur.
    Au plus simple, tu lance un signal qui est connecté au stop du timer.

    Regarde la FAQ :
    http://qt.developpez.com/faq/?page=m...d-appartenance
    http://qt.developpez.com/faq/?page=m...read-connexion

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

Discussions similaires

  1. Colonne de menu déroulant rebelle
    Par Digiwolf dans le forum Access
    Réponses: 9
    Dernier message: 31/01/2006, 09h51
  2. [MySQL] Apostrophes rebelles !!!
    Par JoN28fr dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 13/12/2005, 22h57
  3. [VB6] ActiveChart se rebelle!
    Par rupeni dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 26/11/2005, 17h07
  4. [DW MX 2004] Cadre rebel !
    Par Ticoche dans le forum Dreamweaver
    Réponses: 3
    Dernier message: 29/09/2005, 12h54
  5. [SQL SERVER]des doublons rebelles
    Par trotters213 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 25/03/2005, 15h12

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