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 :

Appel inter-thread ?


Sujet :

Multithreading

  1. #1
    Invité
    Invité(e)
    Par défaut Appel inter-thread ?
    Bonjour à tous.

    J'ai un problème avec un programme que je développe sous Qt Creator.

    Ce programme est composé de son thread principal, celui de la fenêtre graphique EmulatorWindow héritant de QMainWindow, et d'un second thread héritant de QThread chargé de se connecter à un port pour l'écouter.

    La classe du thread "écouteur" dispose d'un pointeur sur la classe de la fenêtre graphique afin de pouvoir appeler la fonction de cette dernière servant à afficher du texte (display()), dans le but de rendre compte en temps réel de l'activité du thread écouteur.

    Il y a donc dans la fonction run() du thread écouteur plusieurs instructions du genre window->display("chaine"). Le compilateur ne râle pas, mais à l'exécution, et seulement au lancement du thread écouteur, ces instruction provoquent l'erreur suivante :

    " QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QTextDocument(0x997450), parent's thread is QThread(0x997180), current thread is QThread(0x9985a0)
    QObject::connect: Cannot queue arguments of type 'QTextBlock'
    (Make sure 'QTextBlock' is registered using qRegisterMetaType().)
    QObject::connect: Cannot queue arguments of type 'QTextCursor'
    (Make sure 'QTextCursor' is registered using qRegisterMetaType().) "

    Cette erreur ne fait pas planter le programme ni n'empêche le thread écouteur de tourner, seulement les appels à display ne fonctionnent pas.

    Donc, si quelqu'un a une solution pour réparer ça, ou même une autre façon de faire susceptible de répondre à mon besoin, je suis preneur.

    EmulatorWindow.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
    #ifndef EMULATORWINDOW_H
    #define EMULATORWINDOW_H
     
    #include <QMainWindow>
     
    class ApplicationThreader;
     
    namespace Ui {
    	class EmulatorWindow;
    }
     
    class EmulatorWindow : public QMainWindow
    {
    		Q_OBJECT
     
    	public:
    		explicit EmulatorWindow(QWidget *parent = 0);
    		~EmulatorWindow();
    		void display(std::string s);
     
    	private:
    		Ui::EmulatorWindow *ui;
    		ApplicationThreader* thread;
     
     
    	public slots:
    		void updateDisplaying();
    };
     
    #endif // EMULATORWINDOW_H
    ApplicationThread.h (le thread écouteur)
    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
    #ifndef APPLICATIONTHREADER_H
    #define APPLICATIONTHREADER_H
     
    #include <QTimer>
    #include <QThread>
    #include <string>
    #include <windows.h>
     
    class EmulatorWindow;
     
    class ApplicationThreader : public QThread
    {
    	public:
    		ApplicationThreader(EmulatorWindow* wind);
    		QTimer* getTimer();
     
    	private:
    		EmulatorWindow* parent;
    		QTimer timer;
    		HANDLE port;
     
    		void run();
    };
    ApplicationThreader.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
    #include "ApplicationThreader.h"
    #include "EmulatorWindow.h"
    #include <iostream>
    using namespace std;
     
    ApplicationThreader::ApplicationThreader(EmulatorWindow* wind):
    	parent(wind),
    	timer(this)
    {
    	timer.start(50);
    }
     
    QTimer* ApplicationThreader::getTimer() {
    	return &timer;
    }
     
    void ApplicationThreader::run() {
    	parent->display("chaine");
            //[...]
    	sleep(3);
    }
    EmulatorWindow.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
    #include "EmulatorWindow.h"
    #include "ApplicationThreader.h"
    #include "ui_EmulatorWindow.h"
     
    EmulatorWindow::EmulatorWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::EmulatorWindow),
        thread(new ApplicationThreader(this))
    {
        ui->setupUi(this);
        QObject::connect(ui->pushButton, SIGNAL(clicked()), thread, SLOT(start()));
        QObject::connect(thread->getTimer(), SIGNAL(timeout()), this, SLOT(updateDisplaying()));
     
    }
     
    EmulatorWindow::~EmulatorWindow()
    {
        delete ui;
    }
     
    void EmulatorWindow::updateDisplaying()
    {
    	ui->label->setText((thread->isRunning() ? "Running" : "Standby"));
    }
     
    void EmulatorWindow::display(std::string s)
    {
    	ui->plainTextEdit->appendPlainText(QString::fromStdString(s));
    }

  2. #2
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    bonjour,

    le message est clair : tu n'as pas le droit d'ajouter du texte dans le QTextDocument parent qui n'est pas dans un autre thread. Par contre tu dois pouvoir t'en sortir aisément avec les signaux et les slots :

    1. Dans le thread contenant le QTextDocument => tu crées un slot pour afficher ta chaine
    2. Dans le thread "secondaire", tu émet un signal (je n'ai jamais testé entre deux threads mais ça doit pouvoir le faire d'après la FAQ (si je sais lire ) dès que tu souhaite afficher une nouvelle chaine.


    La FAQ recommande de prendre des précautions dans ton contexte, et je t'invite à la lire, tu auras surement plus d'info que de ma part (et de plus justes).
    Nullius in verba

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Désolé pour le temps de réponse, j'avais carrément oublié ce message depuis.

    Sur ton conseil, je me suis documenté et je maîtrise à présent beaucoup mieux l'architecture multi-thread permise par Qt. Et effectivement, c'est bien le signaux et les slots qui servent à communiquer entre deux thread différents.

    Merci pour ton aide, cela m'a orienté sur la bonne voie.

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

Discussions similaires

  1. Appel inter thread
    Par duaner dans le forum C#
    Réponses: 3
    Dernier message: 23/11/2007, 18h25
  2. [c#]Communication inter thread
    Par chasse dans le forum Windows Forms
    Réponses: 6
    Dernier message: 18/12/2006, 20h45
  3. Erreur : Opération inter-threads non valide
    Par cadeau dans le forum C++/CLI
    Réponses: 1
    Dernier message: 12/12/2006, 09h07
  4. communication inter-thread en c sous linux
    Par splinternabs dans le forum POSIX
    Réponses: 17
    Dernier message: 22/02/2006, 09h34
  5. Réponses: 15
    Dernier message: 07/07/2005, 11h05

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