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

Qt Discussion :

Thread, freeze GUI et priorités


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut Thread, freeze GUI et priorités
    Bonjour,

    je suis confronté à un problème de freeze GUI dans mon application. Voici le fonctionnement de la partie qui me pose problème :

    L'application est un clavier virtuel doté d'un système d'autocomplétion, cette application est développée pour appareil portable sous Linux Embedded.

    Une classe CompleterWidget étend de QWidget permet d'afficher une liste de mots. Cette liste se met à jour grâce à la classe CompleterThread qui étend de QThread. La classe possède un slot refreshView(const QStringList&) permettant de se mettre à jour en fonction de la liste reçue.

    La classe CompleterThread possède un signal completionListReady(const QStringList&) et une méthode addPrefix(const QString&) qui ajoute un préfixe dans une liste de préfixes. Sa méthode run() tente en boucle de lire la liste de préfixes et de calculer la liste de complétion liée à chaque préfixe. Une fois le calcul fait, le signal completionListReady est émit avec la liste en paramètre.

    Voici comment sont organisées mes classes (simplifié) :

    CompleterWidget.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class CompleterWidget : public QWidget
    {
        Q_OBJECT
     
    public:
         CompleterWidget::CompleterWidget(QWidget * parent);
     
    public slots:
        void refreshView(const QStringList& list);
     
    private:
        CompleterThread * p_completerThread;
    }
    CompleterWidget.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
    CompleterWidget::CompleterWidget(QWidget * parent) : QWidget(parent)
    {
        //Code
     
        p_completerThread  = new CompleterThread(this);
        QObject::connect(p_completerThread, SIGNAL(completionListReady(const QStringList&)), this, SLOT(refreshView(const QStringList&)));
        p_completerThread->start(QThread::LowestPriority);
    }
     
    void CompleterWidget::refreshView(const QStringList& list)
    {
        //Code : rafraichissement du GUI 
        //Temps d'exécution de la fonction entière : environ 3 ms
    }
    CompleterThread.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
    class CompleterThread : public QThread
    {
        Q_OBJECT
     
    public:
        CompleterThread::CompleterThread(QObject * parent);
     
        void run();
        void addPrefix(const QString& prefix);
     
    private:
        bool p_continue;
        QStringList p_prefixList;
        QMutex p_mutex;
     
    signals: 
        void completionListReady(const QStringList&);
    }
    CompleterThread.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
    CompleterThread::CompleterThread(QObject * parent) : QThread(parent)
    {
        //Code
    }
     
    void CompleterThread::run()
    {
        while(p_continue)
        {
            while(!p_prefixList.isEmpty)
            {
                QMutexLocker mlocker(p_mutex);
                QString currentPrefix = p_prefixList.last();
                p_prefixList.clear();
                mlocker.unlock();
     
                QStringList res = calculateCompletionList(currentPrefix); //Calcul long => environ 1000 ms
     
                mlocker.relock()
                if(p_prefixList.isEmpty)
                    emit completionListReady(res);
                //mlocker est détruit à la sortie du bloc
            }
     
            msleep(50);
        }
    }
     
    void CompleterThread::addPrefix(const QString& prefix)
    {
        QMutexLocker mlocker(p_mutex);
        p_prefixList.append(prefix);
    }
    Le problème est le suivant :

    L'application est un clavier virtuel doté d'un système d'autocomplétion.
    Quand j'envoie rapidement (en tapotant sur les touches de mon clavier virtuel) plusieurs requêtes de complétion successives (utilisation de addPrefix()), il y a par moment des freezes d'environ une seconde. Ces freezes sont gênant car empêchent l'utilisation du clavier virtuel pendant quelques instants.

    Je ne comprends pas pourquoi ces freezes ont lieu, ma méthode permettant le rafraichissement de ma GUI ne prend pas plus de 5ms à s'exécuter. Le problème semble venir du thread lui-même qui prendrait toutes les ressources CPU pour faire son calcul (celui-ci dure en moyenne 1000ms).

    NB : je travaille sur appareil portable avec Linux Embedded. Je n'ai évidemment aucun problème de freeze sur PC.

    Ai-je loupé quelque chose quant au fonctionnement des Threads, des priorités?
    Ma méthode est elle adapté à ce que je veux faire?

  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
    Pour le freeze, je ne sais pas trop mais c'est surement lié à cela :

    ta fonction addPrefix n'est pas thread safe => t'as un gros accés concurrent avec la fonction run de ton thread sur p_prefixList => tout peut arrivé, comme un crash

  3. #3
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut
    Comment corriger ça? Mutex?

    J'ai du mal encore à comprendre le fonctionnement des mutex et des concurrents.

  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 Niak74 Voir le message
    Comment corriger ça? Mutex?

    J'ai du mal encore à comprendre le fonctionnement des mutex et des concurrents.
    Dans ton code, seule un mutex peut résoudre ton problème. Regarde dans la FAQ, il y as quelques explications

  5. #5
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut
    Ok, thanks ^^

  6. #6
    Membre expérimenté
    Avatar de Niak74
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    271
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 271
    Par défaut
    J'ai modifié les fonctions run() et addPrefix() dans CompleterThread en y ajoutant du mutex. Est-ce que je suis dans l'idée?

Discussions similaires

  1. thread pour Gui et pour tache temps reel
    Par Pierag dans le forum POSIX
    Réponses: 1
    Dernier message: 26/07/2009, 15h48
  2. thread et GUI
    Par bboy0303 dans le forum Multithreading
    Réponses: 6
    Dernier message: 23/05/2009, 10h27
  3. [Freeze Swing et Threads] Freeze lors d'un appel
    Par Tuxico dans le forum EDT/SwingWorker
    Réponses: 1
    Dernier message: 02/11/2008, 15h53
  4. Réponses: 11
    Dernier message: 24/11/2006, 22h30
  5. [Thread] Priorités face à un bloc synchronisé
    Par Satch dans le forum Concurrence et multi-thread
    Réponses: 10
    Dernier message: 19/01/2006, 10h31

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