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 :

Erreur de thread


Sujet :

Multithreading

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Par défaut Erreur de thread
    Bonjour, je suis également stagiaire. On m'a confier la mission de créer un client afin de piloter un petit robot(wifibot) tout en obtenant des informations en temps réel sur son état grâce à des capteurs installés sur lui. Une grande partie de la programmation se fait en c++ et malheureusement, je ne connais ce langage que depuis peu. Je souhaiter réaliser des boucles d'envoi/réceptions périodiques tant que la connexion via socket est établi,. Pour ne pas bloquer mon programme, j'ai lu que si je voulais réaliser des autres actions en parallèle, il fallait que j'utilise des thread. J'ai utilisé des thread de la classe QThread dans ce but.

    Le problème est que lorsque je compile mon programme, j'obtiens cette erreur
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QTcpSocket(0x8454b90), parent's thread is QThread(0x8454448), current thread is clientServeur(0x8454b88)


    D'après ce que j'ai lu sur d'autres forum, L'enfant d'un QObject doit toujours être crée dans un thread où le parent a été crée, mais le problème est que je ne sais pas du tout comment corriger mon erreur vu que je malgré cette belle explication, je ne la situe pas du tout dans mon programme.
    J'ai également lu qu'il fallait utiliser la fonction movetoThread() mais pareil je ne sais pas comment l'implémenter.

    Je vous donne les liens de documentation que j'ai trouvé:
    - http://qt.developpez.com/faq/?page=Thread
    - http://qt.developpez.com/doc/3.3/qthread/
    - http://qt-labs.developpez.com/thread...-movetothread/

    Je serais très reconnaissant si vous pouviez me guider afin que je trouve la solution de mon problème et me dire comment le résoudre (à l'exception de la classe consigne qui n'est pas importante).

    Je vous donne le code que j'ai produit pour l'instant:

    clientServeur.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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #ifndef CLIENTSERVEUR_H
    #define CLIENTSERVEUR_H
     
    #include <iostream>
    #include <string>
    #include <QtNetwork/QTcpSocket>
    #include <QMutex>
    #include <QThread>
    #include "consigne.h"
    using namespace std;
     
    class clientServeur : public QThread
    {
        Q_OBJECT
     
    private:
     
            QTcpSocket socket; //Socket utilisé pour communiquer avec le robot
     
            QString ipaddr; //adresse IP du robot
     
            const static int LOOPTIME=500000; // Temps en uS  avant deux cycles de lecture/écriture au robot
     
            const static int DEFAULT_PORT=15000;//port TCP de base utilisé pour se connecter au robot
     
            int port; //port tcp
     
            QMutex mutex; //Mutex utilisé pour bloquer l'accès aux variables sbuf et rbuf (Thread)
     
            char rbuf[7]; //variable temporaire de lecture/réception
     
            quint8 sbuf[2];//variable temporaire d'écriture/envoi
     
            bool quit; //On arrête le thread si le booleen "quit" est vrai
     
            int connect(); //Ouvre la connection avec le robot. Cette méthode privée doit être appellé uniquement
                           //par la méthode run() pour débuter la communication avec le serveur robot
    //protected:
     
    public:
            //Les constructeurs et destructeur
            clientServeur() ;//Initialise avec ip=192.168.1.106 et port 15020
            void run();
     
            void lancement_boucle();
     
            clientServeur(string ip); //port 15020
     
            clientServeur(string ip, int ipport);  //Initialise avec ip=192.168.1.106 et port 15020
     
            clientServeur(int port);
     
            ~clientServeur();
     
            void appliquer(Consigne cons); //Applique la commande en fonction de la consigne
                                            //Vérifie d'abord la consigne est valide, puis l'applique.
            void getData(char* data); //obtient des informations du serveur
     
     
     
     
    };
     
    #endif // CLIENTSERVEUR_H
    clientServeur.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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    #include "clientServeur.h"
     
    //Les constructeurs et destructeur
    clientServeur::clientServeur() : port(DEFAULT_PORT), ipaddr("127.0.0.1"), quit(false), QThread()
    {
        start();
    }
     
    clientServeur::clientServeur(string ip, int ipport) : ipaddr(QString(ip.c_str())) , port(ipport), quit(false), QThread()
    {
        start();
    }
     
    clientServeur::clientServeur(string ip): ipaddr(QString(ip.c_str())) , port(DEFAULT_PORT), quit(false), QThread()
    {
        start();
    }
    clientServeur::clientServeur(int nport) : ipaddr("127.0.0.1") , port(nport), quit(false), QThread()
    {
        start();
    }
     
    clientServeur::~clientServeur()
    {
        mutex.lock();
        quit = true;
        mutex.unlock();
        if (!socket.isOpen()) {
            socket.close();
        }
    }
     
    int clientServeur::connect() //Connecte le robot
    {
        if (!socket.isOpen()) {
            socket.connectToHost(ipaddr,DEFAULT_PORT,QIODevice::ReadWrite);
            if (!socket.waitForConnected(-1)) {
                cout<< "ERREUR:"<<socket.errorString().toStdString()<<endl;
                return -1;
            }
            cout<< "SOCKET CONNECTEE" <<endl;
        }
    }
     
     
    void clientServeur::appliquer(Consigne cons) //Aplique la commande, la méthode run() va l'envoyer dans la boucle du thread
    {                                             //c'est pourquoi mutex est fermé!
        // si la consigne est valide
        if (cons.estValide()) {
     
            int vG = cons.getVitG();
            int vD = cons.getVitD();
            int ctrlV = int(cons.getSpeedControl());
            //Moteur Gauche: Avance ou recule; est égale à 1 si ça avance, égale à 0 si ça recule
            int avanceG;
            if ( vG > 0) avanceG = 1;
            else avanceG = 0;
     
            //Moteur Droit: Avance ou recule; est égale à 1 si ça avance, égale à 0 si ça recule
            int avanceD;
            if ( vD > 0) avanceD = 1;
            else avanceD = 0;
     
            cout<<"vG= "<< vG <<" et vD="<< vD <<endl;
     
            mutex.lock(); // ferme le mutex
     
     
            sbuf[0] = quint8(128*ctrlV + 64 * avanceG + abs(vG));        //Moteur gauche
            sbuf[1] = quint8(128*ctrlV + 64 * avanceD + abs(vD));        //Moteur droit
     
            mutex.unlock(); //Dévérouille le mutex
            cout << "commande appliquer exécutée" << endl;
     
        }
    }
     
     
    void clientServeur::getData(char* data)  //Copie le contenu de "rbuf" qui est provisoire(buffer) dans "data"
    {
     
        mutex.lock();
     
        for (int i=0;i<7;i++) {
            data[i] = rbuf[i];
        }
        cout << "data[1] vaut : " << data[1] << endl;
     
        mutex.unlock();
    }
     
     
     
    void clientServeur::run()
    {
        lancement_boucle();
    }
     
    void clientServeur::lancement_boucle()
    {
        if (connect()==-1)
        {
            mutex.lock();
            quit = true;
            mutex.unlock();
        }
     
        cout << "DEMARRAGE THREAD..." <<endl;
     
        while(!quit && socket.isOpen()) {
     
            // On ferme le mutex
            mutex.lock();
            //cout << "début cycle" << endl;
     
            //Envoi Commande
            socket.waitForBytesWritten(300);
            bool nor0 = socket.putChar(sbuf[0]);
            bool nor1 = socket.putChar(sbuf[1]);
            int nb = int(nor0) + int(nor1);
            cout << "Envoie de " << nb << "octets" << endl;
            socket.flush();
     
            //Lecture
            socket.waitForReadyRead(300);
            //cout<< "Octets a lire :"<< socket.bytesAvailable()<< endl;
            int nor = socket.read(rbuf,7); //Lit et dispose dans les rbuffer
           // cout<<"Nombre d'octets lus :"<< nor << endl;
     
            mutex.unlock();
            cout << "fin cycle thread" << endl;
     
            usleep(LOOPTIME);//temps d'attente entre deux boucles envoi/réception
        }
        cout<<"ARRET THREAD"<<endl;
    }
    Robot.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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #ifndef ROBOT_H
    #define ROBOT_H
    #define PI 3.1415926536
     
    #include <QtNetwork/QTcpSocket>
    #include <QMutex>
    #include <string>
    #include "consigne.h"
    #include "clientServeur.h"
     
    #include <iostream>
     
    using namespace std;
     
    class Robot
    {
    private:
            Consigne cons;
            quint8  vitG;
            quint8  vitD;
            quint8  batterie;
            quint8  distG;
            quint8  distD;
            clientServeur *client;
            const static float DIAMETRE = 0.125;
     
    public:
            //Constructeur
            Robot();
            Robot(string ip);
            Robot(Consigne cons);
            ~Robot();
     
            //Méthodes
            void modifier(Consigne cons);
            void modifier(float vitesse); //Donne une consigne de vitesse sans passer par la classe consigne, s'applique aux deux roues
     
            void accelerer();
     
            void ralentir();
     
            void stopper();
     
        //    void tourner(quint8  direction);
     
            quint8  getVitReelleG();
     
            quint8  getVitReelleD();
     
            quint8  getBatterie();
     
            quint8  getDistanceG();
     
            quint8  getDistanceD();
    };
     
    #endif // ROBOT_H
    robot.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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    #include "Robot.h"
     
    Robot::Robot() :vitG(0) , vitD(0), batterie(0), distD(0), distG(0), cons(0,0)
    {
        client = new clientServeur();
    }
     
    Robot::~Robot()
    {
        delete client;
    }
     
    //Méthodes
     
    void Robot::modifier(Consigne cons)
    {
        int vG = cons.getVitG();
        int vD = cons.getVitD();
        cons.modifier(vG, vD); //Modifie la consigne
        if (cons.estValide() == false)
        {
            cons.limiter();
            client->appliquer(cons);
        }
    }
     
    void Robot::modifier(float vitesse) //Donne une consigne de vitesse , s'applique aux deux roues
    {
        cons.modifier(vitesse, vitesse);
        modifier(cons);
     
    }
     
     
    void Robot::accelerer() //Donne une consigne de vitesse, s'applique aux deux roues
    {
        cons.augmenter(5,5);
        if (cons.estValide() == false)
        {
            cons.limiter();
        }
    }
     
    void Robot::ralentir()
    {
        cons.diminuer(5,5);
        if (cons.estValide() == false)
        {
            cons.limiter();
        }
     
    }
     
    void Robot::stopper()
    {
        cons.modifier(0, 0);
    }
     
    /*void Robot::tourner(quint8  direction)
    {
     
    }*/
     
    quint8  Robot::getVitReelleG()
    {
        char data[7];
        quint8  vitGAvant;
        quint8  vitGArriere;
        client->getData(data);
        vitGAvant = (DIAMETRE*PI*quint8 (data[1]))/12;
        vitGArriere = (DIAMETRE*PI*quint8 (data[2]))/12;
        vitG = (vitGAvant + vitGArriere)/2;
        return vitG;
     
    }
     
    quint8  Robot::getVitReelleD()
    {
        char data[7];
        quint8  vitDAvant;
        quint8  vitDArriere;
        client->getData(data);
        vitDAvant = (DIAMETRE*PI*quint8 (data[3]))/12;
        vitDArriere = (DIAMETRE*PI*quint8 (data[4]))/12;
        vitD = (vitDAvant + vitDArriere)/2;
        return vitD;
    }
     
    quint8  Robot::getBatterie()
    {
        char data[7];
        client->getData(data);
        batterie = quint8 (data[0]);
        return batterie;
    }
     
    quint8  Robot::getDistanceG()
    {
        char data[7];
        client->getData(data);
        distG = quint8 (data[5]);
        return distG;
    }
     
    quint8  Robot::getDistanceD()
    {
        char data[7];
        client->getData(data);
        distD = quint8 (data[6]);
        return distD;
    }
    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
    20
    21
    22
    23
    24
    25
    26
    #include <QtCore/QCoreApplication>
    #include <QMutex>
    #include "clientServeur.h"
    #include "consigne.h"
    #include "Robot.h"
    #include <iostream>
     
    using namespace std;
     
    int main(int argc, char *argv[])
    {
        cout << "début application" << endl;
        cout << "Création robot" << endl;
        Robot monrobot;
        cout << "Fin Création robot" << endl;
     
        cout << "début tempo" << endl;
     
        unsigned int i(0);
        while (i<10000000000)
        {
        }
     
        cout << "fin tempo" << endl;
        cout << "fin application" << endl;
    }

    Je serai heureux si vous pouviez m'aider.

  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.
    J'ai regardé vote fait mais dans clientServeur.h rempalce

    QTcpSocket socket;
    par
    QTcpSocket * socket;
    et instancie le dans le run. Comme cela ton QTcpSocket sera associé au bon thread. Sinon il te faut faire un moveToThread dessus avant le start.

    Pour le lock/unlock des mutex, regrade QMutexLocker.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 6
    Par défaut
    Merci beaucoup, je vais essayer ça!

Discussions similaires

  1. Erreur de thread sur JTable triée
    Par boboss123 dans le forum Composants
    Réponses: 5
    Dernier message: 29/04/2014, 16h02
  2. Une erreur de threads
    Par damfle dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 28/08/2012, 20h48
  3. Erreur inter-thread en utilisant le port serie
    Par leo2v2o dans le forum C#
    Réponses: 8
    Dernier message: 16/01/2008, 12h32
  4. pb: erreur inconnue! (thread? command action?)Bluetooth
    Par corseb-delete dans le forum Java ME
    Réponses: 1
    Dernier message: 12/03/2007, 12h57
  5. ASP.NET + opendialog erreur exeption thread
    Par bibifoc dans le forum ASP.NET
    Réponses: 1
    Dernier message: 22/01/2007, 21h45

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