QThreads , QObject et de la fonction de veille
Le problème que j'ai rencontré c'est que j'ai décidé de mettre en œuvre QThreads
la façon dont ils sont censés, basé sur de nombreux articles:
http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
et de la question est que, puisque l'algorithme est exécuté en séparer QObject
(enveloppé dans QThread
) . comment puis-je appeler quelque chose comme Thread::Sleep
ou qch .. des idées ?
Une petite description du logiciel.
Fondamentalement, mon application résout TSP
( problème du voyageur de commerce). Que la recherche va de pair, il enregistre tous les états dans l'histoire comme frames
..(comme les visuels des images). Les algorithmes de recherche sera exécutée sur un seul thread .
Thread principal est la manipulation avec le GUI.
Ensuite, il ya la Mediaplayer
comme thread qui raconte Main
thread quoi une image à afficher sur l'écran. D'où vient donc le sommeil ?
Dans le gui il y a un curseur que l'utilisateur peut utiliser l'avance rapide ou aller dans un rythme normal.. que le curseur indique via le signal de la fente à la Mediaplayer
thread pour aller plus vite ou plus lentement.
le problème, c'est que Qt fait
sleep()
un protected membre de la QThread
classe. Et donc, quand vous écrivez votre fil, comme un logement raccordé à un QThread
's de signal, vous n'avez pas d'accès direct àAh, ok. Eh bien, vous pouvez simplement sous-classe et de "rexport" la fonction, mais pourquoi êtes-vous essayer de dormir de toute façon? Des chronomètres (ou les conditions d'attente) sont souvent une meilleure solution. Si vous expliqué le problème que vous tentez de résoudre, vous auriez probablement obtenir plus d'informations utiles.
pourquoi le
sleep
fonction existe? Parce que parfois, le sommeil est effectivement la bonne solution...La classe QThread est à peine de merde. Quel est votre problème avec elle? Il y a une véritable utilise un thread qui n'est pas basé sur l'événement, puis vous tirer de QThread et réimplémenter
void run()
. Mais le par défaut façon de faire les choses doivent être toujours en ayant asynchrone, run-pour-code d'achèvement des logements dans un QObject. Voir, par exemple, je Déteste RTOSes par Miro Samek embeddedgurus.com/state-space/2010/04/i-hate-rtoses. Puis, lorsque l'analyse comparative montre que le code que vous voulez exécuter est UC privé (que ce soit par le thread GUI, ou le thread qu'il est déjà en cours), vous vous déplacez à un nouveau thread.
OriginalL'auteur Erich Jagomägis | 2012-05-27
Vous devez vous connecter pour publier un commentaire.
Ce que nous avons fait, c'est fondamentalement quelque chose comme ceci: (écrit par la mémoire, comme je n'ai pas de code récupéré sur cet ordinateur)
L'essentiel est que le
QThread::sleep
fonction provoque le thread appelant à dormir, pas la threaf représenté par leQThread
instance. Donc, il suffit de créer un wrapper qui l'appelle via un customQThread
sous-classe.Malheureusement, QThread est un désordre. La documentation indique que vous utilisez de manière incorrecte. Quelques messages de blog, comme vous l'avez trouvé, dites-vous une meilleure façon de le faire, mais vous ne pouvez pas appeler des fonctions comme
sleep
, qui devrait ne jamais avoir été un protégé de threads états, en premier lieu,.Et le meilleur de tous, même peu importe la façon dont vous utilisez QThread, il est conçu pour émuler ce qui est probablement le pire fil API jamais conçu, le code Java. Par rapport à quelque chose de sain, comme
boost::thread
, ou encore mieux,std::thread
, il a gonflé, trop compliqué et inutilement difficile à utiliser et nécessitant une quantité phénoménale de code réutilisable.C'est vraiment l'un des endroits où l'intervalle Qt de l'équipe gâché. Grand moment.
sleep()
est protégé. Vous devriez ne jamais les utiliser. Il doit être privé de tout ce que je soins.Un thread n'est pas "fondamentalement asynchrone". Ce n'est pas une tâche, il n'est pas un pool de threads ou quelque chose comme ça. Et
sleep
est parfois utile. Que faire si je veux appelersleep
sur le thread principal? Allez-vous soutenir que le thread principal est "fondamentalement code asynchrone"?Dans une interface graphique Qt application principale (GUI) thread est censé exécuter court, de l'exécution à l'achèvement des morceaux de code que revenir rapidement à la boucle d'événements. C'est comment event driven cadres sont conçus. Si vous faites quelque chose d'autre, vous ne pouvez pas vous attendre décent comportement de l'application du point de vue de l'utilisateur. Bien sûr, vous pouvez dormir tout ce que vous voulez, mais l'application va se sentir comme de la merde. Ce n'est pas une loi de la nature, c'est juste un choix entre un logiciel qui fonctionne bien et des logiciels qui suce. De votre choix.
bien sûr, le thread GUI doit probablement ne pas dormir (au moins pas pendant qu'il est dans la boucle d'événements), mais où ai-je dit le contraire? Je ne parle même pas des applications avec interface graphique en particulier. mais sur les applications qui utilisent QThreads. Vous faites une déclaration qu'AUCUN fil ne devrait jamais le sommeil, jamais, sous aucun prétexte. Ce qui est absurde.
Oui, si vous dormez dans un QThread il ne peut pas traiter les événements. Pas chaque thread doit traiter les événements. Pas chaque thread possède une boucle d'événements. Certains threads de à usage unique fils. Donc oui, si vous ne pouvez pas imaginer à quel type d'application on besoin de dormir dans a thread (pas nécessairement le principal, mais aucun fil), puis, bien, bon pour vous. Dans ce cas, vous vivez dans un monde plus simple que certains d'entre nous. 🙂
OriginalL'auteur jalf
La réponse est simple: vous n'êtes pas censé bloquer asynchrone, de l'exécution à l'achèvement de code, chaque gestionnaire d'événement et la fente de la mise en œuvre de
QObject
est censé faire son travail et à renvoyer dès que possible. Il n'est pas censé faire toute sorte de occupé attente ou de sommeil. Pour plus d'rodomontades le long de cette ligne, voir Miro Samek de Je déteste RTOSes.Pour une bien meilleure mise en œuvre qui résulte de ce qui précède, voir cette réponse à la place. Macro astuces qui suit ci-dessous est préférable de laisser les pauvres âmes coincé avec C.
J'ai joint un exemple de la façon de faire de la bonne façon, au moins du point de vue de ce que fait le code. Si vous voulez une mise en œuvre réelle, ne cherchez pas plus loin que Du coup de pouce stackless coroutines.
La macro ruse est sucre syntaxique - il fait de la technique le plus agréable au goût (Boost t-il mieux que je le fais ci-dessous). Si vous utilisez des macros ou d'écrire les méthodes explicitement, c'est à vous. La syntaxe est pas ce qui est prétendu être la "bonne façon" de faire. Je suis pas le seul à utiliser ces préprocesseur supercherie. Manque, c'est le soutien des appels de fonctions imbriquées, et plusieurs "threads" de l'exécution à l'achèvement d'exécution au sein d'un
QObject
. Le montre l'exemple de code pour un seul "fil" et un seul niveau de async appels de fonction. Stackless Python prend cela à la conclusion logique.Vous verrez ce modèle dans tous de votre code si vous l'écrire de manière asynchrone. Le
SLEEP
macro est la syntaxe de sucre pour aider à rendre le code plus facile à suivre. Il n'y a pas vraiment propre façon de l'écrire sans hacky macro en C++ où la syntaxe ne serait pas dominateur. Même en C++11, la langue n'a pas de prise en charge intégrée pour le rendement. Voir Pourquoi n'était-ce pas le rendement ajoutée pour C++0x?.C'est vraiment non-blocage de code, vous verrez que le périodique de l'événement timer se déclenche pendant que vous êtes "endormi". Notez que cet multitâche coopératif a beaucoup moins de frais généraux que le thread/processus de bascule fait par le système d'exploitation. Il ya une raison pourquoi les 16 bits de Windows de l'application du code a été écrit de cette manière: il exécute très bien, même sur les maigres matériel.
Noter que ce code ne pas besoin d'un
QThread
, et, en fait, ne pas utiliser deQThread
, bien que si vous voulez déplacer l'objet vers un thread de priorité élevée, les retards aura moins de propagation.L'intervalle Qt de la minuterie de mise en œuvre est assez intelligent pour diminuer le timer tick période sous Windows, si la période est "court". Vous pouvez utiliser la plate-forme spécifique code que j'ai montré ci-dessous, mais il devrait être découragé. Sur Qt 5, il vous suffit de démarrer une
Qt::PreciseTimer
de la minuterie. Notez que sur la pré-Windows 8 de systèmes de négociation hors la consommation d'énergie et légèrement plus élevé dans le noyau de frais généraux pour les performances ici. Windows 8, OS X (xnu) et moderne Linux sont tickless et ne pas souffrir d'une telle dégradation de la performance.Je doit reconnaître que le clair de préprocesseur abus direction de La création de C macro ## et __LINE__ (jeton de concaténation avec le positionnement de la macro).
De même pour la
SLEEP()
macro, vous pouvez également mettre en place unGOTO()
macro, pour vous permettre d'avoir simple des machines à états finis qui sont écrits dans un format plus facile à suivre sur le blocage de style de code, mais sont asynchrones derrière les coulisses. Vous pouvez avoirENTER()
etLEAVE()
des macros pour mettre en œuvre des actions à faire sur l'état d'entrée et de sortie, etc, mais le code peut regarder tout à fait comme un droit codée blocage de style de fonction. J'ai trouvé ça assez productif, et plus facile à suivre que le code qui est dépourvue de toute syntaxique sugarcoating. YMMV. En fin de compte, vous auriez quelque chose qui est sur le chemin de UML diagrammes d'états-transitions, mais avec moins de frais généraux (tous les deux d'exécution de code et de texte-sage) queQStateMachine-based
implémentations.Ci-dessous est la sortie, les astérisques sont minuteur périodique par les tiques.
OriginalL'auteur Kuba Ober
Je suis d'accord avec jalf.com. J'ai un fil qui agit comme une sorte de DBUS démon et les besoins pour écouter les messages à jamais. Deux choses à mentionner:
jalf.com a
Mais ce n'est PAS MILLISECONDES! QThread::sleep() ne prend que quelques secondes. Aussi, si l'un est pour cette approche, il doit également inclure la QThread lib de toute façon, de sorte qu'il pourrait être plus facile de faire l'appel comme ceci:
directement dans le code. De cette façon, il n'y a pas un supplément de fichier d'en-tête. J'ai couru ce et il fonctionne aussi comme jalf.com expliqué. (mettre le thread appelant de dormir.)
OriginalL'auteur MrUser
Pour Qt 4.8.0 (la version que j'utilise),
QThread::sleep
,QThread::msleep
etQThread::usleep
ont été rendues publiques, de sorte que vous pouvez les appeler directement. Dans les précédentes versions de Qt, ils ont étéstatic protected
.par exemple
QThread::sleep(5); //sleep for 5 seconds
OriginalL'auteur Bruce Jia