Marcus Junglasin lähettämä artikkeli
Ohjelmoitaessa tapahtumakäsittelijää Delphissä (kuten Klikkaamalla TB-painikkeen tapahtuma), tulee aika, jolloin sovelluksesi on oltava kiireinen jonkin aikaa, esim. Koodin on kirjoitettava iso tiedosto tai pakattava joitain tietoja.
Jos teet niin, huomaat sen sovelluksesi näyttää lukittuneelta. Lomaketta ei voi enää siirtää, ja painikkeet eivät osoita merkkejä elämästä. Se näyttää kaatuneen.
Syynä on, että Delpi-sovellus on yksikierteinen. Kirjoittamasi koodi edustaa vain joukko proseduureja, joita Delphin pääkierre kutsuu aina tapahtuman tapahtuessa. Loppuosa päälanka käsittelee järjestelmäviestejä ja muita asioita, kuten muotojen ja komponenttien käsittelytoimintoja.
Joten jos et lopeta tapahtumien käsittelyä tekemällä pitkää työtä, estät sovellusta käsittelemään näitä viestejä.
Yleinen ratkaisu tällaisen tyyppisiin ongelmiin on kutsu "Sovellus. ProcessMessages". "Sovellus" on TA-sovellusluokan globaali kohde.
Hakemus. Processmessages käsittelee kaikki odottavat viestit, kuten ikkunan liikkeet, painikkeen napsautukset ja niin edelleen. Sitä käytetään yleisesti yksinkertaisena ratkaisuna pitämään sovelluksesi "toimivana".
Valitettavasti "ProcessMessages" -mekanismilla on omat ominaisuutensa, jotka voivat aiheuttaa suurta sekaannusta!
Mitä ProcessMessages tarkoittaa?
PprocessMessages käsittelee kaikki sovellusviestijonossa odottavat järjestelmäviestit. Windows käyttää viestejä "puhua" kaikille käynnissä oleville sovelluksille. Käyttäjän vuorovaikutus tuodaan muotoon viesteillä ja "ProcessMessages" käsittelee heidät.
Jos esimerkiksi hiiri menee alas TB-painikkeella, ProgressMessages tekee kaiken, mitä tämän tapahtuman pitäisi tapahtua, kuten painikkeen uudelleenmaalaus "painetuksi" tilaan ja tietysti kutsu OnClick () -käsittelyprosessiin, jos olet määrittänyt sellaisen.
Se on ongelma: kaikki ProcessMessages-puhelut saattavat sisältää rekursiivisen puhelun mille tahansa tapahtuman käsittelijälle. Tässä on esimerkki:
Käytä seuraavaa koodia painikkeen OnClick jopa -käsittelijälle ("työ"). For-lause simuloi pitkää prosessointityötä joissakin puheluissa ProcessMessages-palveluihin silloin tällöin.
Tätä on yksinkertaistettu paremman luettavuuden vuoksi:
{MyFormissa:}
WorkLevel: kokonaisluku;
{OnCreate:}
WorkLevel: = 0;
menettely TForm1.WorkBtnClick (Lähettäjä: TObject);
var
sykli: kokonaisluku;
alkaa
lisää (WorkLevel);
varten jakso: = 1 että 5 tehdä
alkaa
Memo1.Lines. Lisää ('- Työ' + IntToStr (WorkLevel) + ', Työkierto' + IntToStr (sykli);
Sovellus. ProcessMessages;
uni (1000); // tai jokin muu työ
pää;
Memo1.Lines. Lisää ('Työ' + IntToStr (WorkLevel) + 'päättynyt.');
joulukuu (WorkLevel);
pää;
ILMA "Prosessiviestit" seuraavat rivit kirjoitetaan muistioon, jos painiketta painetaan kahdesti lyhyessä ajassa:
- Työ 1, työkierto 1
- Työ 1, sykli 2
- Työ 1, sykli 3
- Työ 1, työkierto 4
- Työ 1, sykli 5
Työ 1 päättyi.
- Työ 1, työkierto 1
- Työ 1, sykli 2
- Työ 1, sykli 3
- Työ 1, työkierto 4
- Työ 1, sykli 5
Työ 1 päättyi.
Kun menettely on kiireinen, lomake ei osoita mitään reaktiota, mutta Windows asetti toisen napsautuksen viestijonoon. Heti kun "OnClick" on valmis, sitä kutsutaan uudelleen.
MUKAAN "ProcessMessages", tulos saattaa olla hyvin erilainen:
- Työ 1, työkierto 1
- Työ 1, sykli 2
- Työ 1, sykli 3
- Työ 2, työkierto 1
- Työ 2, sykli 2
- Työ 2, sykli 3
- Työ 2, työkierto 4
- Työ 2, sykli 5
Työ 2 päättyi.
- Työ 1, työkierto 4
- Työ 1, sykli 5
Työ 1 päättyi.
Tällä kertaa muoto näyttää toimivan uudelleen ja hyväksyy kaikki käyttäjän vuorovaikutukset. Joten painiketta painetaan puoliväliin ensimmäisen "työntekijän" toiminton aikana uudelleen, joka käsitellään heti. Kaikkia saapuvia tapahtumia käsitellään kuten mitä tahansa muuta toimintopuhelua.
Teoriassa jokaisen "ProgressMessages" -puhelun aikana MITÄÄN napsautuksia ja käyttäjäviestejä voi tapahtua "paikallaan".
Joten ole varovainen koodisi kanssa!
Eri esimerkki (yksinkertaisella näennäiskoodilla!):
menettely OnClickFileWrite ();
var myfile: = TFileStream;
alkaa
myfile: = TFileStream.create ('myOutput.txt');
yrittää
sillä aikaa BytesReady> 0 tehdä
alkaa
myfile. Kirjoita (DataBlock);
kavennus (BytesReady, koon koko (DataBlock));
DataBlock [2]: = # 13; {testilinja 1}
Sovellus. ProcessMessages;
DataBlock [2]: = # 13; {testilinja 2}
pää;
vihdoin
myfile.free;
pää;
pää;
Tämä toiminto kirjoittaa suuren määrän dataa ja yrittää "avata" sovelluksen lukituksen käyttämällä "ProcessMessages" -sovellusta joka kerta, kun datalohko kirjoitetaan.
Jos käyttäjä napsauttaa painiketta uudelleen, sama koodi suoritetaan, kun tiedostoa vielä kirjoitetaan. Joten tiedostoa ei voi avata toista kertaa ja menettely epäonnistuu.
Ehkä sovelluksesi tekee virheen palautusta, kuten puskurien vapauttamista.
Mahdollisena tuloksena "Datablock" vapautetaan ja ensimmäinen koodi "äkillisesti" nostaa "Käyttörikkomus", kun se käyttää sitä. Tässä tapauksessa: testilinja 1 toimii, testilinja 2 kaatuu.
Parempi tapa:
Helppouden helpottamiseksi voit asettaa koko lomakkeen "käytössä: = epätosi", joka estää käyttäjän syöttämät tiedot, mutta EI Näytä tätä käyttäjälle (kaikki painikkeet eivät ole harmaita).
Parempi tapa olisi asettaa kaikki painikkeet "pois käytöstä", mutta tämä voi olla monimutkaista, jos haluat pitää esimerkiksi yhden "Peruuta" -painikkeen. Lisäksi sinun täytyy käydä läpi kaikki komponentit poistaaksesi ne käytöstä ja kun ne otetaan uudelleen käyttöön, sinun on tarkistettava, onko joku jäljellä käytöstä poissa tilassa.
Sinä voisit poista säilön lapsiohjaukset käytöstä, kun Käytössä oleva ominaisuus muuttuu.
Kuten luokan nimi "TNotifyEvent" ehdottaa, sitä tulisi käyttää vain lyhytaikaisiin reaktioihin tapahtumaan. Aikaa vievä koodi on paras tapa IMHO laittaa kaikki "hidas" koodi omaan säieeseen.
"PrecessMessages" -ongelmien ja / tai komponenttien käyttöönoton ja käytöstä poistamisen yhteydessä toinen säie näyttää olevan lainkaan liian monimutkainen.
Muista, että jopa yksinkertaiset ja nopeat koodirivit voivat roikkua sekunneissa, esim. tiedoston avaaminen levyasemalla saattaa joutua odottamaan, kunnes asema kääntyy loppuun. Se ei näytä kovin hyvältä, jos sovelluksesi näyttää kaatuvan, koska asema on liian hidas.
Se siitä. Seuraavan kerran lisäät "Sovellus. ProcessMessages ", ajattele kahdesti;)