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 :
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 class CompleterWidget : public QWidget { Q_OBJECT public: CompleterWidget::CompleterWidget(QWidget * parent); public slots: void refreshView(const QStringList& list); private: CompleterThread * p_completerThread; }
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 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.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 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&); }
Le problème est le suivant :
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); }
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?
Partager