Die dunkle Seite von Application.ProcessMessages in Delphi-Anwendungen

Artikel eingereicht von Marcus Junglas

Beim Programmieren eines Ereignishandlers in Delphi (wie dem OnClick Ereignis eines TButton) kommt die Zeit, zu der Ihre Anwendung eine Weile beschäftigt sein muss, z. Der Code muss eine große Datei schreiben oder einige Daten komprimieren.

Wenn Sie das tun, werden Sie das bemerken Ihre Bewerbung scheint gesperrt zu sein. Ihr Formular kann nicht mehr verschoben werden und die Schaltflächen zeigen kein Lebenszeichen. Es scheint abgestürzt zu sein.

Der Grund ist, dass eine Delpi-Anwendung Single-Threaded ist. Der Code, den Sie schreiben, stellt nur eine Reihe von Prozeduren dar, die vom Hauptthread von Delphi aufgerufen werden, wenn ein Ereignis eintritt. In der restlichen Zeit verarbeitet der Hauptthread Systemnachrichten und andere Dinge wie Formular- und Komponentenhandhabungsfunktionen.

Wenn Sie Ihre Ereignisbehandlung nicht durch langwierige Arbeit abschließen, verhindern Sie, dass die Anwendung diese Nachrichten verarbeitet.

Eine übliche Lösung für derartige Probleme ist der Aufruf von "Application.ProcessMessages". "Application" ist ein globales Objekt der Klasse TApplication.

Die Application.Processmessages verarbeitet alle wartenden Nachrichten wie Fensterbewegungen, Tastenklicks usw. Es wird häufig als einfache Lösung verwendet, um die Funktion Ihrer Anwendung aufrechtzuerhalten..

Leider hat der Mechanismus hinter "ProcessMessages" seine eigenen Eigenschaften, was große Verwirrung stiften kann!

Was bedeutet ProcessMessages??

PprocessMessages verarbeitet alle wartenden Systemnachrichten in der Anwendungsnachrichtenwarteschlange. Windows verwendet Nachrichten, um mit allen laufenden Anwendungen zu "kommunizieren". Die Benutzerinteraktion wird über Nachrichten auf das Formular gebracht und von "ProcessMessages" verarbeitet.

Wenn die Maus zum Beispiel auf einen TButton zeigt, erledigt ProgressMessages alles, was bei diesem Ereignis passieren sollte, wie das Neuanmalen der Schaltfläche in einen "gedrückten" Zustand und natürlich einen Aufruf der OnClick () - Behandlungsprozedur, falls Sie dies wünschen zugewiesen.

Das ist das Problem: Jeder Aufruf von ProcessMessages kann einen erneuten rekursiven Aufruf eines Ereignishandlers enthalten. Hier ist ein Beispiel:

Verwenden Sie den folgenden Code für den OnClick Even-Handler einer Schaltfläche ("work"). Die for-Anweisung simuliert einen langen Verarbeitungsjob mit gelegentlichen Aufrufen von ProcessMessages.

Dies ist zur besseren Lesbarkeit vereinfacht:

 in MyForm:
  WorkLevel: Ganzzahl;
OnCreate:
  WorkLevel: = 0;
Verfahren TForm1.WorkBtnClick (Absender: TObject);
var
  Zyklus: ganze Zahl;
Start
  inc (WorkLevel);
  zum Zyklus: = 1 zu 5 tun
  Start
    Memo1.Lines.Add ('- Work' + IntToStr (WorkLevel) + ', Cycle' + IntToStr (cycle);
    Application.ProcessMessages;
    Schlaf (1000); // oder eine andere Arbeit
  Ende;
  Memo1.Lines.Add ('Work' + IntToStr (WorkLevel) + 'ended.');
  dec (WorkLevel);
Ende;

OHNE "ProcessMessages" werden folgende Zeilen in das Memo geschrieben, wenn der Button in kurzer Zeit ZWEIMAL gedrückt wurde:

 - Arbeit 1, Zyklus 1
- Arbeit 1, Zyklus 2
- Arbeit 1, Zyklus 3
- Arbeit 1, Zyklus 4
- Arbeit 1, Zyklus 5
Arbeit 1 beendet.
- Arbeit 1, Zyklus 1
- Arbeit 1, Zyklus 2
- Arbeit 1, Zyklus 3
- Arbeit 1, Zyklus 4
- Arbeit 1, Zyklus 5
Arbeit 1 beendet.