Den mörka sidan av applikationen. Processmeddelanden i Delphi-applikationer

Artikel lämnad av Marcus Junglas

När du programmerar en händelsehanterare i Delphi (som OnClick händelse av en TButton), kommer det den tid då din ansökan måste vara upptagen ett tag, t.ex. koden måste skriva en stor fil eller komprimera vissa data.

Om du gör det kommer du att märka det din ansökan verkar vara låst. Din form kan inte flyttas längre och knapparna visar inga tecken på liv. Det verkar ha kraschat.

Anledningen är att en Delpi-applikation är enkeltrådad. Koden du skriver representerar bara ett gäng procedurer som kallas av Delphis huvudtråd närhelst en händelse inträffade. Resten av tiden hanterar huvudtråden systemmeddelanden och andra saker som form- och komponenthanteringsfunktioner.

Så om du inte avslutar din händelsehantering genom att göra lite långt arbete kommer du att förhindra att applikationen hanterar dessa meddelanden.

En vanlig lösning för sådana problem är att kalla "Application.ProcessMessages". "Application" är ett globalt objekt för TApplication-klassen.

Application.Processmessages hanterar alla väntande meddelanden som fönsterrörelser, knappklick och så vidare. Det används ofta som en enkel lösning för att hålla din applikation "fungerar".

Tyvärr har mekanismen bakom "ProcessMessages" sina egna egenskaper, vilket kan orsaka stor förvirring!

Vad gör ProcessMessages?

PprocessMessages hanterar alla meddelanden om väntande system i meddelandekön för applikationer. Windows använder meddelanden för att "prata" med alla program som körs. Användarinteraktion bringas till formuläret via meddelanden och "ProcessMessages" hanterar dem.

Om musen till exempel går ner på en TButton, gör ProgressMessages allt som borde hända på den här händelsen som ommålningen av knappen till ett "pressat" tillstånd och, naturligtvis, ett samtal till OnClick () hanteringsproceduren om du tilldelad en.

Det är problemet: alla samtal till ProcessMessages kan innehålla ett rekursivt samtal till alla händelseshanterare igen. Här är ett exempel:

Använd följande kod för en knapps OnClick even handler ("arbete"). För-uttalandet simulerar ett långt bearbetningsjobb med några samtal till ProcessMessages då och då.

Detta förenklas för bättre läsbarhet:

 i MyForm:
  WorkLevel: heltal;
OnCreate:
  WorkLevel: = 0;
procedur TForm1.WorkBtnClick (avsändare: TObject);
var
  cykel: heltal;
Börja
  inc (WorkLevel);
  för cykel: = 1 till 5 do
  Börja
    Memo1.Lines.Add ('- Work' + IntToStr (WorkLevel) + ', Cycle' + IntToStr (cykel);
    Application.ProcessMessages;
    sömn (1000); // eller något annat arbete
  slutet;
  Memo1.Lines.Add ('Work' + IntToStr (WorkLevel) + 'slut.');
  dec (WorkLevel);
slutet;

UTAN "ProcessMessages" skrivs följande rader till memo, om knappen trycktes två gånger på en kort tid:

 - Arbeta 1, cykel 1
- Arbeta 1, cykel 2
- Arbete 1, cykel 3
- Arbete 1, cykel 4
- Arbete 1, cykel 5
Arbetet 1 slutade.
- Arbeta 1, cykel 1
- Arbeta 1, cykel 2
- Arbete 1, cykel 3
- Arbete 1, cykel 4
- Arbete 1, cykel 5
Arbetet 1 slutade.