Le côté obscur d'Application.ProcessMessages dans les applications Delphi

Article soumis par Marcus Junglas

Lors de la programmation d'un gestionnaire d'événements dans Delphi (comme le Sur clic en cas de TButton), il arrive un moment où votre application doit être occupée pendant un certain temps, par ex. le code doit écrire un gros fichier ou compresser certaines données.

Si vous faites cela, vous remarquerez que votre application semble bloquée. Votre formulaire ne peut plus être déplacé et les boutons ne montrent aucun signe de vie. Il semble être écrasé.

La raison en est qu'une application Delpi est monothread. Le code que vous écrivez ne représente qu'un tas de procédures qui sont appelées par le thread principal de Delphi chaque fois qu'un événement se produit. Le reste du temps, le thread principal gère les messages système et d'autres choses comme les fonctions de gestion des formulaires et des composants.

Donc, si vous ne terminez pas la gestion de vos événements en effectuant un long travail, vous empêcherez l'application de gérer ces messages.

Une solution courante pour ce type de problèmes consiste à appeler "Application.ProcessMessages". "Application" est un objet global de la classe TApplication.

L'application.Processmessages gère tous les messages en attente, tels que les mouvements de fenêtre, les clics sur les boutons, etc. Il est couramment utilisé comme une solution simple pour faire fonctionner votre application.

Malheureusement, le mécanisme derrière "ProcessMessages" a ses propres caractéristiques, ce qui peut provoquer une grande confusion!

Qu'est-ce que ProcessMessages?

PprocessMessages gère tous les messages système en attente dans la file d'attente de messages des applications. Windows utilise des messages pour "parler" à toutes les applications en cours d'exécution. L'interaction de l'utilisateur est apportée au formulaire via des messages et "ProcessMessages" les gère.

Si la souris descend sur un TButton, par exemple, ProgressMessages fait tout ce qui doit se produire sur cet événement comme la repeindre le bouton à un état "enfoncé" et, bien sûr, un appel à la procédure de gestion OnClick () si vous attribué un.

C'est le problème: tout appel à ProcessMessages peut contenir à nouveau un appel récursif à n'importe quel gestionnaire d'événements. Voici un exemple:

Utilisez le code suivant pour le gestionnaire OnClick pair d'un bouton ("work"). L'instruction for simule un long travail de traitement avec quelques appels à ProcessMessages de temps en temps.

Ceci est simplifié pour une meilleure lisibilité:

 dans MyForm:
  WorkLevel: entier;
OnCreate:
  WorkLevel: = 0;
procédure TForm1.WorkBtnClick (expéditeur: TObject);
var
  cycle: entier;
commencer
  inc (WorkLevel);
  pour cycle: = 1 à 5 faire
  commencer
    Memo1.Lines.Add ('- Work' + IntToStr (WorkLevel) + ', Cycle' + IntToStr (cycle);
    Application.ProcessMessages;
    sommeil (1000); // ou un autre travail
  fin;
  Memo1.Lines.Add ('Work' + IntToStr (WorkLevel) + 'terminé.');
  dec (WorkLevel);
fin;

SANS "ProcessMessages", les lignes suivantes sont écrites dans le mémo, si le bouton a été enfoncé deux fois en peu de temps:

 - Travail 1, cycle 1
- Travail 1, cycle 2
- Travail 1, cycle 3
- Travail 1, cycle 4
- Travail 1, cycle 5
Fin du travail 1.
- Travail 1, cycle 1
- Travail 1, cycle 2
- Travail 1, cycle 3
- Travail 1, cycle 4
- Travail 1, cycle 5
Fin du travail 1.