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

PyQt Python Discussion :

Fonctionnement d'une classe Worker en thread


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Doctorant
    Inscrit en
    Avril 2014
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 27
    Par défaut Fonctionnement d'une classe Worker en thread
    Bonjour à tous,

    J'ai une question d'ordre "fonctionnel" sur l'utilisation d'une classe Worker en thread. Je crois avoir compris dans les grandes lignes signaux/slots. Je ne suis pas un connaisseur de Qt en Python ou en C mais je vois l'idée et l'intérêt.

    Je fais un GUI qui permettra de piloter beaucoup d'appareils et de gérer de multiples tâches dans le même temps. Idéalement j'imagine qu'en C++ je gagnerai en optimisation mais à l'instant t j'ai surtout des SDK Python...

    Pour cela j'ai fait un main.py avec une interface et je cherche à avoir plusieurs processus que je peux lancer depuis le main (acquisition de données).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      self.worker= Worker(self.data_1, self.data_2, self.data_3)
                self.thread_1 = QtCore.QThread()
                self.worker.moveToThread(self.thread_1)
                self.thread_1.start()
    Puis dans le Worker je lance un while...
    Mais lorsque j'ai un signal dans le main et que je veux lancer une fonction dans le Worker (type update d'un paramètre) et que j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.worker.methode_1(self.update_data1)
    est-ce que cela utilise le main ou le worker d'un point de vue thread ?
    Je remarque que j'ai souvent des freezes et je soupçonne d'avoir mal optimisé les utilisations des threads qui permettrait de fluidifier l'interface.

    Peut-être que ce n'est pas très clair
    Merci

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Un des motifs courants de plantage avec QThread est quand on oublie qu'il ne doit pas comporter d'instruction graphique! Il n'est pas "thread-safe" (https://fr.wikipedia.org/wiki/Thread_safety).

    A part ça, je préfère utiliser une classe héritant de QThread plutôt que le "moveToThread". Voilà un petit code pour illustrer mon propos:

    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
    class Operationlongue(QtCore.QThread):
     
        # création des nouveaux signaux
        info = QtCore.pyqtSignal(int) # signal pour informer d'une progression
        fini = QtCore.pyqtSignal(bool, list) # signal pour la fin du thread
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
            self.stop = False # drapeau pour exécuter une demande d'arrêt
     
        #========================================================================
        def run(self):
            """partie qui s'exécute en tâche de fond
            """
            for i in range(0, 101):
                if self.stop:
                    break # arrêt anticipé demandé
                time.sleep(0.05)
                self.info.emit(i) # envoi du signal de progression d'exécution
            # fin du thread
            self.fini.emit(self.stop, [1,2,3]) # envoi du signal de fin d'exécution
     
        #========================================================================
        def arreter(self):
            """pour arrêter avant la fin normale d'exécution du thread
            """
            self.stop = True
    Dans ce code, seule la méthode "run" est exécutée en tâche de fond. Ainsi, on peut appeler la méthode "arreter" qui change la variable stop pour arrêter la boucle for. Et quand la méthode run est terminée, le thread est terminé aussi.

  3. #3
    Membre averti
    Homme Profil pro
    Doctorant
    Inscrit en
    Avril 2014
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 27
    Par défaut
    Bonjour et merci de ta réponse.

    Je comprends un peu la notion de thread-safe et je n'y suis pas du tout avec mon programme. Car j'ai mon main, qui gère l'interface graphique à cela j'ajoute deux threads avec QThread (moveToThread, il y a une raison spécifique à ne pas utiliser cette fonction?) et un troisième qui est géré avec le module threading.

    Séparément tout va bien mais ensemble ça ne fonctionne pas forcément très bien. Je vais relire en détail pour voir si je ne trouve pas des erreurs et des conflits. Par contre je vois que ce n'est pas Thread-safe d'utiliser des échanges entre les threads (mais bon j'ai parfois besoin de faire ça et je voulais m'éviter de passer par le main...)

    Peut-être qu'il aurait été plus intelligent de faire le GUI lui aussi dans un thread et pas dans le main...

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 742
    Par défaut
    Salut,

    Citation Envoyé par Winounet Voir le message
    Peut-être qu'il aurait été plus intelligent de faire le GUI lui aussi dans un thread et pas dans le main...
    Vous avez des pages de documentations/tutos (dans la documentation Qt) qui racontent ce qu'on peut faire avec et quand faire quoi... notamment que les objets du GUI ne peuvent être que dans le thread principal.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre averti
    Homme Profil pro
    Doctorant
    Inscrit en
    Avril 2014
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 27
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,



    Vous avez des pages de documentations/tutos (dans la documentation Qt) qui racontent ce qu'on peut faire avec et quand faire quoi... notamment que les objets du GUI ne peuvent être que dans le thread principal.

    - W
    Oui j'ai lu de la documentation et je continue d'en lire pour essayer de mieux comprendre le problème de mon soft, et j'ai vérifié déjà avec un seul thread, j'émets un signal et des 3 floats et j'ai l'impression que ça ne va pas aussi vite que je voudrais à l'affichage. Bref, c'est sans doute un combat avec moi-même qu'il reste
    Mais ma question principale est répondue, je crois, un Worker permet de faire une opération spécifique mais ensuite quand j'émets des commandes depuis le thread principal pour update des datas dans le Worker je prends de la mémoire dans le thread principal?
    Je marche un peu sur des oeufs quand même en disant ça. J'aimerais bien finalement avoir plusieurs threads principaux imbriqués les uns dans les autres avec même des bouts de GUI indépendants afin de ne pas ralentir un bout du soft quand j'update une commande sur un autre bout du soft.

Discussions similaires

  1. Accès aux données d'une classe par plusieurs threads
    Par Dalini71 dans le forum Threads & Processus
    Réponses: 3
    Dernier message: 08/12/2013, 07h23
  2. Communication entre une classe et un thread
    Par cs_ntd dans le forum C#
    Réponses: 2
    Dernier message: 24/10/2008, 10h49
  3. partager l'instance d'une classe entre plusieurs thread ?
    Par contremaitre dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 29/07/2008, 11h53
  4. Réponses: 3
    Dernier message: 25/03/2008, 09h46
  5. Thread avec une fonction membre d'une classe
    Par SteelBox dans le forum Windows
    Réponses: 6
    Dernier message: 01/03/2004, 01h15

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