Чланак поднио Марцус Јунглас
Приликом програмирања алата за обраду догађаја у Делпхију (као што је ОнЦлицк догађај ТБуттон-а), долази време када апликација мора да буде заузета неко време, нпр. код треба написати велику датотеку или компримовати неке податке.
Ако то учините, примијетићете то чини се да је ваша апликација закључана. Образац се више не може померати, а тастери не показују траг живота. Изгледа да се срушио.
Разлог је тај што је Делпи апликација једносмерна. Код који пишете представља само гомилу поступака које Делпхи зове главна нит кад год се догоди неки догађај. Преостало време главна нит обрађује системске поруке и друге ствари као што су форме и функције руковања компонентама.
Дакле, ако не завршите са обрађивањем догађаја дуготрајним радом, спречићете апликацију да обрађује те поруке.
Уобичајено решење за овакав тип проблема је да се позове „Апликација. ПроцессМессагес ". "Апликација" је глобални објект класе ТАпплицатион.
Апликација. Процессмессагес обрађује све поруке на чекању као што су покрети прозора, кликови на дугме и тако даље. Обично се користи као једноставно решење како би апликација остала у функцији.
Нажалост, механизам који стоји иза „ПроцессМессагес“ има своје карактеристике, које могу изазвати велике збрке!
Шта су ПроцессМессагес?
ПпроцессМессагес обрађује све системске поруке у чекању у редовима порука апликација. Виндовс користи поруке да "разговара" са свим покренутим апликацијама. Интеракција корисника доводи се у образац путем порука и "ПроцессМессагес" их рукује.
Ако се миш спусти на ТБуттон, на пример, ПрогрессМессагес учини све што би се требало десити на овом догађају, на пример поновно премештање дугмета у „притиснуто“ стање и, наравно, позив у поступак руковања ОнЦлицк () ако сте га додељели.
У томе је проблем: сваки позив ПроцессМессагес може поново садржавати рекурзивни позив било којем руковатељу догађаја. Ево примера:
Користите следећи код за онЦлицк обрађивач дугмета на тастеру ("рад"). Изјава за фор-лине симулира дугачак процес обраде са неким позивима у ПроцессМессагес.
Ово је поједностављено ради боље читљивости:
{у МиФорм-у:}
ВоркЛевел: цели број;
{ОнЦреате:}
ВоркЛевел: = 0;
процедура ТФорм1.ВоркБтнЦлицк (Пошиљалац: ТОбјецт);
вар
циклус: цели број;
започети
инц (ВоркЛевел);
за циклус: = 1 до 5 урадити
започети
Мемо1.Линес. Адд ('- Ворк' + ИнтТоСтр (ВоркЛевел) + ', Цицле' + ИнтТоСтр (циклус);
Апликација. ПроцессМессагес;
сан (1000); // или неко друго дело
крај;
Мемо1.Линес. Додај ('Рад' + ИнтТоСтр (ВоркЛевел) + 'завршио.');
дец (ВоркЛевел);
крај;
БЕЗ "ПроцессМессагес" у меморију се уписују следећи редови, ако је дугме у кратком времену притиснуто двапут:
- Рад 1, циклус 1
- Рад 1, циклус 2
- Рад 1, циклус 3
- Рад 1, циклус 4
- Рад 1, циклус 5
Рад 1 је завршен.
- Рад 1, циклус 1
- Рад 1, циклус 2
- Рад 1, циклус 3
- Рад 1, циклус 4
- Рад 1, циклус 5
Рад 1 је завршен.
Док је процедура заузета, образац не показује никакву реакцију, али други клик је Виндовс ставио у ред порука. Одмах по довршетку „ОнЦлицк“ позиваће се поново.
Укључујући "ПроцессМессагес", излаз може бити врло различит:
- Рад 1, циклус 1
- Рад 1, циклус 2
- Рад 1, циклус 3
- Рад 2, циклус 1
- Рад 2, циклус 2
- Рад 2, циклус 3
- Рад 2, циклус 4
- Рад 2, циклус 5
Рад 2 је завршен.
- Рад 1, циклус 4
- Рад 1, циклус 5
Рад 1 је завршен.
Овај пут чини се да образац поново ради и прихвата било какву интеракцију корисника. Дакле, дугме се притисне на пола пута током ваше прве "радничке" функције ПРОТИВ, којом ћете руковати одмах. Сви долазни догађаји обрађују се као и било који други позиви функција.
Теоретски, током сваког позива на „ПрогрессМессагес“ може се догодити било који број кликова и корисничких порука „на месту“.
Зато будите опрезни са својим кодом!
Другачији пример (у једноставном псеудо коду!):
процедура ОнЦлицкФилеВрите ();
вар мифиле: = ТФилеСтреам;
започети
мифиле: = ТФилеСтреам.цреате ('миОутпут.ткт');
покушати
док БитесРеади> 0 урадити
започети
мифиле. Врите (ДатаБлоцк);
дец (БитесРеади, сизеоф (ДатаБлоцк));
ДатаБлоцк [2]: = # 13; {тест линија 1}
Апликација. ПроцессМессагес;
ДатаБлоцк [2]: = # 13; {тест линија 2}
крај;
напокон
мифиле.фрее;
крај;
крај;
Ова функција пише велику количину података и покушава „откључати“ апликацију користећи „ПроцессМессагес“ сваки пут када се запише блок података.
Ако корисник поново кликне на дугме, извршит ће се исти код док датотека још увијек пише. Дакле, датотеку не можете отворити други пут и поступак не успе.
Можда ће ваша апликација извршити неки опоравак грешака попут ослобађања међуспремника.
Као могући резултат "Датаблоцк" ће бити ослобођен и први код ће "изненада" покренути "Кршење приступа" када му приступи. У овом случају: испитна линија 1 ће радити, тестна линија 2 ће се срушити.
Бољи начин:
Да би вам било лакше, могли бисте поставити цео образац "омогућено: = лажно", који блокира све корисничке уносе, али НИЈЕ то показао кориснику (сви тастери нису у сивој боји).
Бољи начин би био да се сви тастери поставе на „онемогућено“, али то може бити сложено ако желите да задржите на пример једно дугме „Откажи“. Такође требате проћи све компоненте да бисте их онемогућили и када су поново омогућене, морате проверити да ли би требало да остане још неких у стању онеспособљености.
Ти би могао онемогућите контроле надређених спремника када се промени својство Омогућено.
Као што име класе „ТНотифиЕвент“ сугерише, требало би га користити само за краткотрајне реакције на догађај. За дуготрајан код, најбољи начин је ИМХО да сву "спору" шифру стави у властити Тхреад.
Што се тиче проблема са „ПрецессМессагес“ и / или омогућавањем и онемогућавањем компоненти, употреба а друга нит изгледа да уопште није превише компликовано.
Имајте на уму да чак и једноставне и брзе линије кода могу висити неколико секунди, нпр. отварање датотеке на диску можда ће морати да сачека док се диск заврши. Не изгледа баш добро ако се чини да се ваша апликација руши јер је диск превише спор.
То је то. Следећи пут кад додате „Апликацију. ПроцессМессагес ", размислите два пута;)