Je ne comprends pas quelle Application.ProcessMessages en Delphi est en train de faire
Je suis un noobie en Delphi, donc désolé pour toute question idiote.
Mon superviseur m'a expliqué que l'Application.ProcessMessages empêche le gel de l'application et alloue supplémentaire de temps de calcul. Mais dans les docs de cette commande est toujours quelque chose a expliqué sur un système de file d'attente qui est traitée?
Svp quelqu'un peut-il m'expliquer le contexte?
- C'est absurde. En aucune façon il "attribue supplémentaire en temps de calcul". Et il n'est pas "prévient le gel de l'application"; il force l'application à traiter tous les messages en attente qui, dans une longue course code exécuté dans le main (UI) fil permet à l'INTERFACE utilisateur ressemble, il est vivant. Mais il ne faut jamais exécuter un long code en cours d'exécution dans le thread principal et donc vous ne devriez jamais avoir besoin d'utiliser
Application.ProcessMessages
. - Écrire du code qui n'appelle jamais
Application.ProcessMessages
et n'a jamais besoin de l'appeler. - Voir ce, docwiki.embarcadero.com/Libraries/XE6/en/...
- double possible de Delphi: Comment faire pour éviter qu'un seul thread de l'application de perdre des réponses?
- Lecture recommandée, Le Côté Sombre de l'Application.ProcessMessages.
- Que devrait être une lecture obligatoire.
- parce que c'est un bon post qui suit sur cette question. Je ne pense pas que c'est un dupe, cependant - c'est une façon de faire de la question et ce n'est plus un comment-fait-il-travail en question.
- Vous ne pouvez pas comprendre ProcessMessages jusqu'à ce que vous avez une connaissance approfondie de Windows files d'attente de messages. Un DONC, la question n'est pas la façon de gagner de cette compréhension. La question est donc trop large. Je vous suggère de maître de la file d'attente de message en premier. Je voudrais également écho TLama de l'instruction que votre superviseur est ignorant de ce qui ProcessMessages. Vous apprendrez rien de ce superviseur. Trouver plus qualifié muse.
- Il pourrait être l'affiche de la compréhension de ce que le superviseur a dit. Il pourrait très bien avoir dit, régulièrement appel processmessages dans certains long travail de traitement permettrait d'éviter l'application de semble bloquée, mais subirait supplémentaire de temps de calcul.
- Je pense que vous pouvez comprendre ProcessMessages même lorsque vous n'avez qu'une connaissance superficielle de files d'attente de messages. Dans une situation de vie réelle j'ai pu l'expliquer en 2 minutes. Sur DONC ça peut prendre un peu plus de temps (je ne suis pas un fast typer). Les conseils de "maître de la file d'attente de messages premier" avant d'essayer de saisir ce que la Demande.ProcessMessages ne se sent à moi comme apprendre à construire une voiture avant d'obtenir votre permis de conduire.
- Je me demande si vous avez votre réponse.
- Je pense que le réglage avec une compréhension superficielle de la file d'attente de message est ce qui conduit à la abuise et l'utilisation abusive de ProcessMessages.
Vous devez vous connecter pour publier un commentaire.
N'est pas à court façon de répondre à cette question correctement.
Le principal moyen par lequel les applications Windows interagir avec le système d'exploitation via un système de messagerie. Tout ce qui se passe dans une application windows qui se produit en réponse à un message.
Par exemple :
Si vous cliquez sur l'écran, le système d'exploitation décide de l'application qui ai cliqué et des postes un message à cette demande, indiquant qu'il a reçu un clic (avec l'emplacement du clic).
Si une fenêtre est déplacée et révèle une partie de votre application en dessous d'elle, le système d'exploitation envoie un message indiquant que votre demande de repeindre.
La liste est longue. Tout ce qui arrive est entraînée par des messages.
Maintenant, chaque application dispose d'une primaire thread d'interface utilisateur (le "Principal" thread) et ce fil a une fonction première, il s'exécute dans une boucle infinie qui vérifie ces messages à partir du système d'exploitation, puis exécute le code nécessaire en réponse à ces messages.
Le Problème
Vous venez de commencer l'écriture d'une application. Vous pouvez écrire du code comme ceci :
Dans la plus grande structure du programme, de l'exécution du thread principal ressemble à ceci:
Donc cette boucle est heureusement wizzing quand soudain, l'un des associés gestionnaires (
Button1Click
ci-dessus) commence à prendre un temps très long à remplir. Clés pour comprendre, c'est que l'un gestionnaire de message doit se terminer avant la prochaine, pouvez exécuter. Si vous cliquez sur une barre de défilement, par exemple, et faites-le glisser, mais vous avez branché un gestionnaire deOnClick
de la barre de défilement qui prend 10s pour terminer, puis le faire glisser l'opération ne sera pas vu par votre application jusqu'à ce que le gestionnaire de clic complète. En attendant, le message de la file d'attente se remplit et le thread principal est de ne rien faire à ce sujet.Vous avez sûrement connu ça - tout à coup, votre demande ne répond pas aux clics. Vous ne pouvez pas interagir avec elle, vous ne pouvez pas déplacer la fenêtre, si vous faites glisser une autre fenêtre autour de overtop de l'application n'a même pas de redessiner lui-même - il se remplit avec n'importe quelle poubelle que vous avez laissé sur le dessus.
Entrer ProcessMessages
Les paresseux, terrible solution pour ne pas mettre votre longue-exécution de code dans un thread
Ce que vous faites lorsque vous appelez
Application.ProcessMessages
est, au milieu de l'un de ces gestionnaires, demandant le thread principal pour prendre une pause, de revenir en arrière pour vérifier le message de la file d'attente et vide tous les messages qui s'accumulent; à la poignée de clics, de la fenêtre de mouvements, les entrées, les frappes de touches, à repeindre si nécessaire, etc.Elle semble à première vue comme une chose sensée à faire car il vous permet de garder l'application sensibles au cours d'une longue boucle. En fin de compte, cependant, ce style de programmation est largement considéré comme extrêmement pauvres pratique pour un grand nombre de très bonnes raisons. Il suffit de dire que partout où vous êtes tentés d'utiliser
Application.ProcessMessages
est un dossier solide pour le déplacement de ce travail à un thread d'arrière-plan à la place.Pour plus de détails, nous allons jeter un coup d'oeil au code :
Ainsi quand vous faites cet appel à
Application.ProcessMessages
vous exécutez une boucle qui est, un par un, la vidange des messages de la file d'attente de messages (et d'exécuter le code qui est attaché à des gestionnaires qui sont à réagir à ces messages) jusqu'à ce qu'elle est vide. Quand il est vide et il n'y a plus de messages à traiter, le contrôle sera de retour à la ligne suivante dans votre programme.Le point important à retenir est que le fluide, lisse interaction vous rencontrez lors de l'utilisation d'un programme est une illusion complète qui repose exactement sur cette boucle de message en cours de traitement aussi rapidement que possible. Plus le délai entre la réception d'un message posté à votre demande et le message en cours de manipulation, plus votre application va se sentir comme il est vivant et réactif.
C'est pour cette raison que tout le code qui est attaché à l'interface utilisateur des gestionnaires doit être rapide en cours d'exécution. Long de l'exécution des opérations doivent être interrompue afin que le message de manipulation peut continuer (c'est à dire:
Application.ProcessMessages
) ou ces opérations doivent être déplacés vers un thread séparé où ils peuvent exécuter sans bloquer le thread principal et de le prendre loin de sa responsabilité principale (qui est de garder l'interface utilisateur de son vivant).Pour un très bon article sur le sujet, voir :
Une Clé de l'Odyssée par Pierre-Dessous
(Cache de Google lien... le serveur semble occupé pour moi)
Résumé: Cet article suit la trajectoire d'une frappe de message par le biais de la VCL. Vous apprendrez comment la clé de traitement est mis en place, comment le OnKey des événements et quels points d'intervention pour le programmeur peut être trouvé dans l'ensemble du processus. En outre, des choses comme le traitement de message sont expliqués, et vous apprendrez comment les messages de trace dans le débogueur à partir de la boucle de message à leur destination finale.
What is ProcessMessages Doing?
, pasWhy is it a bad idea?
.Application.ProcessMessages
sont racontés. C'est aussi un total de paille homme. Mettez votre long de l'exécution de code dans un thread et regarder les mêmes problèmes avec les re-entrancy se produire si l'INTERFACE n'a pas désactivé les contrôles qui initient des actions de l'utilisateur qui, actuellement, ne peut en toute sécurité être lancé. Une fois que l'on fixe des appels àApplication.ProcessMessages
sont généralement pas plus de problèmes que ce soit. (En ignorant la possibilité de débordements de pile, à laquelle aucune réponse jusqu'à présent mentionne.)ProcessMessages
est. Le vrai problème avecProcessMessages
est qu'il encourage un style de codage qui fait mal, étroitement associés, difficile de refactoriser, spaghetti/dieu applications qui finissent par être un cauchemar à maintenir s'ils sont autorisés à être trop gros.Application.ProcessMessages
ne devrait probablement pas être l'écriture du code multithread, soit, que le raisonnement à propos de l'exécution asynchrone est similaire.The lazy, terrible solution to not putting your long-running code into a thread
De messagerie
Un Delphi VCL application est une application de Windows et beaucoup de communication entre les composants de Windows (comme les formes, les zones d'édition, mais aussi caché des choses comme des chronomètres) est fait en utilisant des choses que l'on appelle messages.
Ces messages sont envoyés à une file d'attente spéciale. Vous pouvez envoyer des messages directement (à l'aide de la
SendMessage
etPostMessage
fonctions de l'API), mais les messages sont envoyés indirectement lorsque vous définissez une propriété, comme leText
d'unTEdit
.Ces messages sont utilisés pour informer les contrôles que d'importants événements ont eu lieu au sein du programme afin qu'ils puissent répondre de façon appropriée. Que le concept de l'envoi des messages et y répondre est le principe de base d'un paradigme connu comme la programmation événementielle.
De nombreux systèmes d'exploitation modernes sont pilotés par les événements, tels que Windows. En fait, la VCL Delphi enveloppements beaucoup de fonctionnalités de Windows, et beaucoup de choses que vous n'entraînera dans les messages envoyés entre les contrôles, qui notifient ces contrôles de clics de souris, le clavier, les presses, les paramètres Windows de la modification, de l'application de clôture, contrôle de mouvement, etc.
Mainthread ne pas traiter les messages lors de l'exécution de code
Systèmes d'exploitation permettent également des programmes pour les choses ont appelé fils. Les Threads sont comme de petits morceaux d'un programme qui semblent fonctionner en même temps (et dans certains cas réellement faire exécutées simultanément). Une application peut avoir plus d'un thread, mais il y a toujours le thread principal, qui est aussi le thread responsable de l'acceptation des messages entrants et la mise à jour de l'interface graphique.
Lorsque le thread principal de l'application est inactive (pas l'exécution de code), il va vérifier la file d'attente pour voir si il y a des messages et de les traiter. Tout autre code est en cours d'exécution, ce ne peut pas arriver. Considérons cet exemple:
Si vous exécutez ce code, vous attendez l'étiquette pour obtenir un titre de "Une", ce qui change à " B " cinq secondes plus tard. Mais ce n'est pas vrai. Réglage de la légende de l'étiquette déclenche une mise à jour de la commande par un message. Parce que le thread principal est toujours bloqué par ce code (même par la commande de mise en Veille), le message n'a pas encore été traités.
Seulement lorsque les 5 secondes se sont écoulées et la légende est défini à "B", le thread principal devient inactif et exécutera le repeint que nous avons déclenché par réglage de la légende. Notez également que l'interaction, par exemple en cliquant sur un bouton ou en faisant glisser la fenêtre sont reportées jusqu'à ce que les 5 secondes se sont écoulées. L'ensemble de l'INTERFACE utilisateur se bloque alors que le thread principal est l'exécution de ce code.
Application.ProcessMessages à la rescousse
Application.ProcessMessages va forcer l'application à vider son message de la file d'attente, de sorte que vous pouvez régler le code comme ceci:
Habituellement, il ne sera pas seulement un Sommeil dans votre code, mais beaucoup de traitement réel. En utilisant
Application.ProcessMessage
fréquemment, vous pouvez garder l'interface de l'application répondre, même lorsque vous êtes à l'exécution de code.Mais c'est un peu sale, le thread principal (et l'interface) sera toujours bloqué, sauf si vous parvenez à le presser dans un beaucoup d'appels à
Application.ProcessMessages
. Et outre le traitement des messages de peinture, d'autres messages sont traités en tant que bien, afin que l'application puisse traiter un événement de clic droit dans le milieu de votre processus.Donc les docs que vous lisez sont à droite:
Application.ProcessMessages
de vider la message de la file d'attente. Votre superviseur n'est pas tout à fait exact. Il n'a pas d'allouer plus de temps de traitement par dire, mais il intègre la vidange de la file d'attente de message dans le code qui est exécuté, alors que normalement, les messages restent dans la file d'attente jusqu'à ce que l'application devient inactif.Internes
En interne, l'application elle-même fait la même chose tout le temps. Sa procédure principale,
Application.Run
, ressemble à ceci (simplifié pseudo-code):C'est le traitement qui exécute le code, par exemple lorsqu'un
WM_MOUSECLICK
message est traité, il sera le déclencheur (par le biais de certains de Delphi VCL magie), votreButton1Click
gestionnaire d'événement. Puisque c'est un seul thread, tout fonctionne de manière séquentielle, de sorte que vous allez comprendre queProcessMessageFromTheQueue
renvoie uniquement lorsque le gestionnaire d'événement est terminé. Delphi gère un seul message à la fois, et seulement le lendemain, lors de la précédente est terminée.Ou est-il?
Application.ProcessMessages
ressemble à ceci:De sorte qu'il est presque le même que la demande principale de la boucle: il sélectionne un message de la file d'attente et les processus. Donc, cela signifie que vous pouvez réellement traiter les prochains messages pendant que vous êtes à l'intérieur du traitement de la dernière. Une astuce pratique, mais il peut facilement faire votre demande de désordre et de provoquer toutes sortes d'effets secondaires indésirables.
Le droit chemin: Threads
La plupart des gens considèrent que c'est une meilleure solution pour utiliser un thread séparé pour l'exécution de votre code et juste envoyer des signaux vers le thread principal lorsqu'il a besoin de mise à jour d'une étiquette ou d'une barre de progression. De cette façon, le thread principal est en veille tout le temps, et continuera de répondre aux clics de la souris etc.
Threading est difficile pour un débutant, cependant. Certaines choses à garder à l'esprit:
De toute façon, cette réponse ne devrait pas être un cours complet sur les threads, mais maintenant au moins vous savez ce que
Application.ProcessMessages
est pour.A noter également, il est considéré comme "mauvais" par beaucoup de gens, mais en tant que débutant, vous pouvez essayer quand même de trouver ses forces et ses faiblesses par vous-même. Si vous le faites, j'espère que cette information permettra au moins de vous en inspirer pour déplacer des filets dès que vous avez assez d'expérience pour le prochain chapitre.
Sleep(5000)
dans le thread GUI est un cauchemar pour une application Windows. Mise à jour d'un contrôle n'est pas un problème grave du tout comparé à d'autre ce qui peut arriver.