Partea întunecată a aplicației.ProcessMessages în Delphi Applications

Articol trimis de Marcus Junglas

Când programați un handler de evenimente în Delphi (cum ar fi OnClick evenimentul unui TButton), vine momentul în care cererea trebuie să fie ocupată o perioadă, de ex. codul trebuie să scrie un fișier mare sau să comprimeze unele date.

Dacă faci asta, vei observa asta aplicația dvs. pare blocată. Formularul dvs. nu mai poate fi mutat și butoanele nu arată niciun semn de viață. Se pare că s-a prăbușit.

Motivul este că o aplicație Delpi este single threaded. Codul pe care îl scrieți reprezintă doar o mulțime de proceduri care sunt numite de firul principal al lui Delphi ori de câte ori a avut loc un eveniment. Restul timpului, firul principal este gestionarea mesajelor sistemului și a altor lucruri, cum ar fi funcțiile de gestionare a formei și componentelor.

Așadar, dacă nu terminați gestionarea evenimentelor efectuând o muncă îndelungată, veți împiedica aplicația să gestioneze acele mesaje.

O soluție obișnuită pentru un astfel de tip de probleme este să apelați „Application.ProcessMessages”. „Aplicația” este un obiect global al clasei TApplication.

Application.Processmessages gestionează toate mesajele în așteptare, cum ar fi mișcările ferestrei, clicurile de buton șamd. Este utilizat în mod obișnuit ca o soluție simplă pentru ca aplicația dvs. să „funcționeze”.

Din păcate, mecanismul din spatele „ProcessMessages” are propriile sale caracteristici, care ar putea provoca confuzii mari!

Ce face ProcessMessages?

PprocessMessages gestionează toate mesajele sistemului de așteptare din coada de mesaje a aplicațiilor. Windows folosește mesaje pentru a „vorbi” cu toate aplicațiile rulante. Interacțiunea utilizatorilor este adusă în formular prin mesaje și „ProcessMessages” le gestionează.

Dacă mouse-ul coboară pe un TButton, de exemplu, ProgressMessages face tot ce ar trebui să se întâmple la acest eveniment, cum ar fi revopsirea butonului la o stare „apăsată” și, desigur, un apel la procedura de gestionare OnClick (), dacă alocat unul.

Aceasta este problema: orice apel către ProcessMessages ar putea conține din nou un apel recursiv la orice handler event. Iată un exemplu:

Utilizați codul următor pentru un handler OnClick (chiar „de lucru”) al unui buton. Declarația for simulează o lucrare de procesare îndelungată cu unele apeluri la ProcessMessages din când în când.

Aceasta este simplificată pentru o mai bună lizibilitate:

 în MyForm:
  WorkLevel: număr întreg;
OnCreate:
  WorkLevel: = 0;
procedură TForm1.WorkBtnClick (Expeditor: TObject);
var
  ciclu: număr întreg;
începe
  inc (WorkLevel);
  pentru ciclu: = 1 la 5 do
  începe
    Memo1.Lines.Add ('- Work' + IntToStr (WorkLevel) + ', Cycle' + IntToStr (cycle);
    Application.ProcessMessages;
    somn (1000); // sau alte lucrări
  Sfârșit;
  Memo1.Lines.Add ('Work' + IntToStr (WorkLevel) + 'încheiat.');
  dec (WorkLevel);
Sfârșit;

FĂRĂ „ProcessMessages”, următoarele linii sunt scrise în memorie, dacă butonul a fost apăsat de două ori pe două ori:

 - Munca 1, ciclul 1
- Lucrul 1, ciclul 2
- Lucrul 1, ciclul 3
- Lucrul 1, ciclul 4
- Lucrul 1, ciclul 5
Munca 1 s-a încheiat.
- Munca 1, ciclul 1
- Lucrul 1, ciclul 2
- Lucrul 1, ciclul 3
- Lucrul 1, ciclul 4
- Lucrul 1, ciclul 5
Munca 1 s-a încheiat.