Rakenduse tume külg. Protsessisõnumid

click fraud protection

Artikli esitas Marcus Junglas

Delfis sündmuste käitleja programmeerimisel (näiteks OnClick TB nupu sündmus), saabub aeg, mil teie rakendus peab olema mõnda aega hõivatud, nt kood peab kirjutama suure faili või pakkima mõned andmed.

Kui teete seda, märkate seda tundub, et teie rakendus on lukustatud. Teie vormi ei saa enam teisaldada ja nupud ei näita elumärke. See näib olevat kukkunud.

Põhjus on see, et Delpi rakendus on ühe keermega. Teie kirjutatav kood tähistab lihtsalt hunnikut protseduure, mida Delphi põhilõng kutsub esile sündmuse toimumisel. Ülejäänud aja põhiteema on süsteemisõnumite ja muude asjade, näiteks vormi ja komponentide käsitsemise funktsioonide käsitlemine.

Seega, kui te ei lõpeta sündmuste käsitlemist mõne pika tööga, takistate rakendusel neid teateid haldamast.

Sellist tüüpi probleemide levinum lahendus on helistada rakendusele. Protsessisõnumid ". Rakendus on TApplication klassi globaalne objekt.

Taotlus. Protsessiteated käsitlevad kõiki ootel sõnumeid, nagu akna liikumised, nuppude klõpsud ja nii edasi. Seda kasutatakse tavaliselt lihtsa lahendusena, et hoida teie rakendus töös.

instagram viewer

Kahjuks on "ProcessMessages" -mehhanismil oma eripärad, mis võib põhjustada suurt segadust!

Mida ProcessMessages pakub?

PprocessMessages haldab kõiki rakenduste sõnumite järjekorras olevaid süsteemisõnumeid. Windows kasutab sõnumeid kõigi töötavate rakendustega rääkimiseks. Kasutajate interaktsioon viiakse vormile sõnumite kaudu ja "ProcessMessages" tegeleb nendega.

Näiteks kui hiir laskub näiteks TB-nupul, teeb ProgressMessages kõik, mis sellel sündmusel juhtuma peaks, nagu näiteks nupu uuesti värvimine "vajutatud" olekusse ja muidugi kutse OnClicki () käitlemisprotseduurile, kui selle määrasite.

See on probleem: iga ProcessMessages'i kõne võib sisaldada uuesti rekursiivset kõnet sündmuste käitlejale. Siin on näide:

Kasutage nuppu OnClicki isegi töötleja ("töö") jaoks järgmist koodi. Väljavõtte avaldus simuleerib pikka töötlemist, kus mõni aeg-ajalt kutsub ProcessMessages'i.

Parema loetavuse huvides on see lihtsustatud:

{MyFormis:}
WorkLevel: täisarv;
{OnCreate:}
Töötase: = 0;
protseduur TForm1.WorkBtnClick (saatja: TObject);
var
tsükkel: täisarv;
alustada
inc (WorkLevel);
jaoks tsükkel: = 1 kuni 5 teha
alustada
Memo1.Liinid. Lisa ('- Töö' + IntToStr (WorkLevel) + ', Tsükkel' + IntToStr (tsükkel);
Rakendus. Protsessisõnumid;
uni (1000); // või mõni muu töö
lõpp;
Memo1.Liinid. Lisa ('Töö' + IntToStr (WorkLevel) + 'lõppes.');
detsember (WorkLevel);
lõpp;

ILMA "protsessisõnumid" kirjutatakse memosse järgmised read, kui nuppu lühikese aja jooksul kaks korda vajutada:

 - 1. töö, 1. tsükkel
- 1. töö, tsükkel 2
- 1. töö, tsükkel 3
- 1. töö, tsükkel 4
- 1. töö, tsükkel 5
1. töö lõppes.
- 1. töö, 1. tsükkel
- 1. töö, tsükkel 2
- 1. töö, tsükkel 3
- 1. töö, tsükkel 4
- 1. töö, tsükkel 5
1. töö lõppes.

Kui protseduur on hõivatud, siis vorm ei reageeri, kuid teine ​​klõps pandi Windowsi teatejärjekorda. Kohe pärast "OnClicki" valmimist helistatakse uuesti.

KAasa "ProcessMessages", võib väljund olla väga erinev:

 - 1. töö, 1. tsükkel
- 1. töö, tsükkel 2
- 1. töö, tsükkel 3
- 2. töö, tsükkel 1
- 2. töö, tsükkel 2
- 2. töö, tsükkel 3
- 2. töö, tsükkel 4
- 2. töö, tsükkel 5
Töö 2 lõppes.
- 1. töö, tsükkel 4
- 1. töö, tsükkel 5
1. töö lõppes.

Seekord näib, et vorm töötab uuesti ja nõustub mis tahes kasutaja sekkumisega. Nii et teie esimese "töötaja" taaskasutamise funktsiooni ajal vajutatakse nuppu poolenisti, mida hakatakse kohe kasutama. Kõiki saabuvaid sündmusi käsitletakse nagu kõiki muid funktsioonikõnesid.

Teoreetiliselt võib iga programmi "ProgressMessages" kõne ajal IGA MÕTTE klõpse ja kasutaja sõnumeid juhtuda "paigas".

Nii et ole oma koodiga ettevaatlik!

Erinev näide (lihtsas pseudokoodis!):

protseduur OnClickFileWrite ();
var myfile: = TFileStream;
alustada
myfile: = TFileStream.create ('myOutput.txt');
proovida
samas BytesReady> 0 teha
alustada
myfile. Kirjuta (DataBlock);
kahanda (BytesReady, suurus (DataBlock));
Andmeplokk [2]: = # 13; {testliin 1}
Rakendus. Protsessisõnumid;
Andmeplokk [2]: = # 13; {testliin 2}
lõpp;
lõpuks
myfile.free;
lõpp;
lõpp;

See funktsioon kirjutab suure hulga andmeid ja proovib rakenduse "lahti võtta", kasutades "ProcessMessages" iga kord, kui andmeplokk kirjutatakse.

Kui kasutaja klõpsab uuesti nuppu, siis käivitatakse sama kood faili kirjutamise ajal. Nii et faili ei saa teist korda avada ja protseduur nurjub.

Võib-olla teeb teie rakendus mõne tõrke taastamise, näiteks puhvrite vabastamise.

Võimaliku tulemusena vabastatakse andmebaas "Datablock" ja esimene kood tõstab sellele juurdepääsu korral äkki "juurdepääsu rikkumise". Sel juhul: 1. testliin töötab, 2. testliin jookseb kokku.

Parem viis:

Lihtsuse huvides võiksite kogu vormi seada "lubatud: = vale", mis blokeerib kogu kasutaja sisestuse, kuid EI MÄRKIGE seda kasutajale (kõik nupud pole hallid).

Parem viis oleks seada kõik nupud "keelatuks", kuid see võib osutuda keerukaks, kui soovite näiteks hoida ühte nuppu "Tühista". Samuti peate nende keelamiseks läbima kõik komponendid ja kui need on uuesti lubatud, peate kontrollima, kas mõni neist peaks olema keelatud olekus.

Sa võiksid keelake konteinerikontroll lapse omaduste lubamisel muutmise korral.

Nagu klassinimi "TNotifyEvent" soovitab, tuleks seda kasutada ainult sündmuse lühiajaliseks reageerimiseks. Aeganõudva koodi jaoks on parim viis IMHO panna kogu "aeglane" kood oma lõime.

"PrecessMessages" probleemide ja / või komponentide lubamise ja keelamise korral tuleb kasutada teine ​​niit tundub, et see pole üldse liiga keeruline.

Pidage meeles, et isegi lihtsad ja kiired koodiridad võivad riputada sekunditeks, nt. võib-olla peab faili avamine kettaseadmel ootama, kuni draiv on üles keritud. See ei tundu eriti hea, kui teie rakendus tundub krahhivat, kuna draiv on liiga aeglane.

See selleks. Järgmisel korral lisate rakenduse "Rakendus. Protsessisõnumid ", mõelge kaks korda;)

instagram story viewer