Kontrola ładowania i zamykania aplikacji – jakie macie patenty?

0

Mamy większą aplikację lub grę (nieistotne), która podczas rozruchu ładuje różne dane z plików zewnętrznych – zawartość plików konfiguracyjnych, obrazy itd. Niektóre dane są wymagane (np. obrazy), bez których program nie może działać prawidłowo, a niektóre są potrzebne (np. konfiguracja), choć możliwe jest pominięcie ich ładowania. Podczas zamykania programu, zwalniana jest pamięć i pewne dane są z powrotem zapisywane na dysku (np. konfiguracja).

Kod źródłowy składa się z dziesiątek klas, służących do reprezentowania tych danych. Jakieś listy z obrazami, drzewka obiektów z najróżniejszymi danymi zassanymi z konfigów itd. Niektóre z tych obiektów opakowują po kilka innych, tworząc drzewka.

I teraz meritum – weźmy pod lupę rozruch. Podczas ładowania danych może się zdarzyć, że któregoś potrzebnego pliku nie ma (np. obraz) i leci wyjątek, albo zawartość pliku konfiguracyjnego jest skopana (zmatolona struktura xml) i trzeba zapytać użytkownika co robić – resetować czy anulować rozruch (ubić program). To samo przy zamykaniu programu – nie da się zapisać konfiguracji, bo odmowa dostępu lub jakikolwiek inny problem.

W jaki sposób kontrolujecie obsługę błędów i dajecie użytkownikowi możliwość wyboru co robić? A dokładniej pytając, w jaki sposób ładujecie dane do obiektów, aby z jednej strony dało się poinformować użytkownika i dopytać co robić jeśli wystąpi błąd, a z drugiej strony, aby kod źródłowy nie wyglądał jak śmietnik?


Samo zagadnienie wydaje się trudne do ogarnięcia, więc dorzucę jeszcze trochę, coby było ciekawiej. ;)

Mamy obiekt, który wewnątrz posiada osadzonych kilka mniejszych. Główny obiekt np. reprezentuje całe drzewo z pliku konfiguracyjnego i ma główną metodę LoadFromFile. W tej metodzie otwierany jest plik konfiguracyjny, a nastepnie wołane są metody LoadFromTree każdego osadzonego obiektu, przekazując im konkretną gałąź drzewa konfiguracji. Każdy z tych obiektów ładuje swoje porcje danych.

Meritum – kilka osadzonych obiektów załaduje swoje porcje, ale jeden z nich nie będzie w stanie i walnie wyjątkiem. W jaki sposób obsłużycie ten błąd, tak aby użytkownik dostał komunikat i mógł pominąć ładowanie danej gałęzi lub całkowicie przerwać proces rozruchu? Pozwolicie wydostać się wyjątkowi poza główną metodę LoadFromFile czy obsłużycie go wewnątrz?


Ogólnie chciałbym się dowiedzieć jakie macie techniki pisania kodu realizującego taką kontrolę błędów i interakcję z użytkownikiem. Ja wiem, że najłatwiej byłoby komunikat wyświetlić wewnątrz LoadFromFile i w razie wciśnięcia przez użytkownika przycisku Abort po prostu dupnąć Halt i mieć problem z głowy, ale takie coś raczej nazwałbym potworkiem, a nie dobrą architekturą programu.

No, zapraszam do dyskusji.

1

Zrób fabryki do wczytywania danych i tworzenia obiektów. Obiekty wewnętrzne powinny implementować dany interface ale tworzone winny być na zewnątrz w fabryce a klasa pobierana z kontenera żeby oddzielić używanie klasy od implementacji. Takie obiekty powinny być wstrzykiwane przez konstruktor lub właściwość. Ofc dialog powinien być w kodzie interfacu gdzie wywołuje fabrykę - fabryka zwraca wyjątek i w kodzie usera a nie fabryki pytasz czy haltowac czy kontynuować kreacje.

0

Masz jakiś krótki PoC ilustrujący to o czym napisałeś? Albo jakąś lekturę?

Początkowo (bo deadline potwornie gonił…) klasy zaprojektowałem w sposób zgodny z uniwersalnymi kontenerami, takimi jak np. TStrings, czyli każdą wyposażyłem w metodę LoadFrom*. To pozwoliło mi szybko zaimplementować ładowanie danych, a na kontrolę błędów i tak nie było czasu, więc się tym nie przejmowałem – drutowałem kod na szybko (i teraz mam za swoje). Fabrykę bym zrobił, ale musiałbym sporo kodu przerobić, a nie za bardzo mi się to opłaca – dlatego dopytuję o ciekawe pomysły, niekoniecznie logiczne/popularne. ;)

Jeden z takich ”dziwnych” pomysłów mam, który pozwoli dodać pełną kontrolę błędów i interakcję z użytkownikiem, bez dużych zmian w kodzie i robienia bajzlu, ale na razie nie będę pisał o nim, coby nie podpowiadać.

2

Moim zdaniem ta dokumentacja nie dokumentuje jedynie frameworka (który nie jest tylko frameworkiem do jednego np. dostępu do bazy, czy robienia webapi - mORMot posiada tak wiele elementów, że jest jakby sposobem na kreacje aplikacji), a dodatkowo zawiera bardzo dobre wstępy teoretyczne do różnych podejść, pokazując na Pascalu wszystko. Rozdział 15.2 powinien pokazać co chciałem przekazać, natomiast całość jest pożyteczna. Dokumentacja trochę waży bo 25MB, ale pobrałem sobie i czytam. Uważam, że to skarbnica wiedzy. Z drugiej strony warto zobaczyć jakie podejście jest np. w C# np, poczytaj o Autofacu czy kontenerze DI z .net core.

0

Nie pasuje mi tu fabryka – to bez sensu. No bo jak, mam tworzyć fabrykę, która tylko raz w trakcie sesji stworzy tylko jednen obiekt? Gdybym miał mieć cały zestaw obiektów do utworzenia, gdzie każdy obiekt ma wspólną klasę-rodzica, to by to miało ręce i nogi, ale tak to tylko zapaskudzę kod i dołożę sobie masę roboty.

Tutaj potrzeba czegoś na kształt callbacków, aby uniknąć implementowania logiki dotyczącej interakcji z użytkownikiem wewnątrz klas z danymi. Ewentualnie coś w formie zdarzeń wstrzykiwanych z zewnątrz.

0
furious programming napisał(a):

Mamy większą aplikację lub grę (nieistotne), która podczas rozruchu ładuje różne dane z plików zewnętrznych – zawartość plików konfiguracyjnych, obrazy itd. Niektóre dane są wymagane (np. obrazy), bez których program nie może działać prawidłowo, a niektóre są potrzebne (np. konfiguracja), choć możliwe jest pominięcie ich ładowania. Podczas zamykania programu, zwalniana jest pamięć i pewne dane są z powrotem zapisywane na dysku (np. konfiguracja).

Kod źródłowy składa się z dziesiątek klas, służących do reprezentowania tych danych. Jakieś listy z obrazami, drzewka obiektów z najróżniejszymi danymi zassanymi z konfigów itd. Niektóre z tych obiektów opakowują po kilka innych, tworząc drzewka.

To, tak naprawdę nie ma znaczenia, ponieważ mięso problemu leży gdzie indziej.

Ale tak przy okazji; ja zawsze takich przypadkach opieram się na automatycznej serializacji i deserialziacji obiektów.
To mnie całkowicie zwalnia z ręcznym wiązaniem obiektów z danymi i łatwo pozwala na rozwijanie modelu danych dla konfiguracji z pełnym wsparciem odczytu konfiguracji z różnych wersji modelu danych obiektów konfiguracji.
Tu jest trochę zabawy, aby zrobić to ogólnie, ale warto.

I teraz meritum – weźmy pod lupę rozruch. Podczas ładowania danych może się zdarzyć, że któregoś potrzebnego pliku nie ma (np. obraz) i leci wyjątek, albo zawartość pliku konfiguracyjnego jest skopana (zmatolona struktura xml)

Przy poprawnej deserializacji jesteś odporny na takie problemy.
Poprawnej, tj takiej, która potrafi odczytać dane z pliku, który nie jest w 100% zgodny z modelem obiektowym.

i trzeba zapytać użytkownika co robić – resetować czy anulować rozruch (ubić program). To samo przy zamykaniu programu – nie da się zapisać konfiguracji, bo odmowa dostępu lub jakikolwiek inny problem.

W jaki sposób kontrolujecie obsługę błędów i dajecie użytkownikowi możliwość wyboru co robić? A dokładniej pytając, w jaki sposób ładujecie dane do obiektów, aby z jednej strony dało się poinformować użytkownika i dopytać co robić jeśli wystąpi błąd, a z drugiej strony, aby kod źródłowy nie wyglądał jak śmietnik?


Samo zagadnienie wydaje się trudne do ogarnięcia, więc dorzucę jeszcze trochę, coby było ciekawiej. ;)

Mamy obiekt, który wewnątrz posiada osadzonych kilka mniejszych. Główny obiekt np. reprezentuje całe drzewo z pliku konfiguracyjnego i ma główną metodę LoadFromFile. W tej metodzie otwierany jest plik konfiguracyjny, a nastepnie wołane są metody LoadFromTree każdego osadzonego obiektu, przekazując im konkretną gałąź drzewa konfiguracji. Każdy z tych obiektów ładuje swoje porcje danych.

Meritum – kilka osadzonych obiektów załaduje swoje porcje, ale jeden z nich nie będzie w stanie i walnie wyjątkiem. W jaki sposób obsłużycie ten błąd, tak aby użytkownik dostał komunikat i mógł pominąć ładowanie danej gałęzi lub całkowicie przerwać proces rozruchu?

Ty się zastanów co chcesz zrobić.
Czym innym jest pominięcie brakującej danej podczas odczytu i nie jest to sytuacja krytyczna, a czym innym brak istotnych danych dla aplikacji.
To pierwsze to na pewno nie wyjątek raczej ostrzeżenie do logu.
To drugie, to zawsze wyjątek.

I po trzecie - moim zdaniem, możesz całkowicie pominąć kwestie związane z powiadamianiem i oczekiwaniem decyzji od użytkownika.
Nawet jeśli dostarczysz mechanizm który będzie zbierał feedback od usera to i tak najprawdopodobniej będzie on (feedback, nie mechanizm) nieprawidłowy.
Wg mnie lepiej całkowicie darować sobie moment czekania na decyzję usera. A może i nawet powiadamiania...

Dlaczego?
Ano dlatego, że najpewniej user w przypadku problemu i tak nic z nim nie zrobi lub robi źle.
O ile Ty będziesz userem, to pewnie będziesz w stanie ocenić czy brak jakiejś konfiguracji jest krytyczny i nie można jej pominąć lub nie.
Ty tak, a inni? Nie sądzę.

Poza tym, co to za informacja "nie udało się załadować XYZ czy kontynuować"?
Kontynuujemy, ale nie załadowano - nie wiem - layoutu programu i nic nie widać.
Apka niby działa, ale co z tego?
Lepiej samemu w kodzie zdecydować co jest krytyczne i musi być, a co nie jest nie zostało załadowane i jedziemy z ustawieniami domyślnymi.

Pozwolicie wydostać się wyjątkowi poza główną metodę LoadFromFile czy obsłużycie go wewnątrz?


Ogólnie chciałbym się dowiedzieć jakie macie techniki pisania kodu realizującego taką kontrolę błędów i interakcję z użytkownikiem. Ja wiem, że najłatwiej byłoby komunikat wyświetlić wewnątrz LoadFromFile i w razie wciśnięcia przez użytkownika przycisku Abort po prostu dupnąć Halt i mieć problem z głowy, ale takie coś raczej nazwałbym potworkiem, a nie dobrą architekturą programu.

To można rozwiązać na wiele rożnych sposobów.
Najprostszy to implementacja interfejsu np. IConfiguration przez delegację dla każdej klasy, która posiada zapis/odczyt konfiguracji.
Implementacja może być dostarcza różna i w różny sposób - nawet przez kontener IoC.

No, zapraszam do dyskusji.

Tu chyba nie ma za bardzo o czym dyskutować, ponieważ wiele zależy od tego czego oczekujesz i jak to już zaimplementowałeś.
Możemy dyskutować o np. czymś co ja nazywam Generic Persistance Layer, ale...
To jest dość skomplikowane i większość ludzi nie widzi sensu w tym aby mieć jeden ogólny mechanizm na odczyt i zapis konfiguracji. Taki mechanizm który przynosi całkowicie przezroczystą obsługę konfiguracji hierarchicznej, gdzie każde node w konfiguracji może być przechowywany w osobnym pliku, jednym pliku dla wielu node'ów lub w bazie danych.

Mi to było potrzebne, to sobie zrobiłem.
Ale nie będę dyskutował o szczegółach, bo to nie ma większego sensu.

0
furious programming napisał(a):

Nie pasuje mi tu fabryka – to bez sensu. No bo jak, mam tworzyć fabrykę, która tylko raz w trakcie sesji stworzy tylko jednen obiekt?

Dlaczego jeden obiekt?
Sam pisałeś o całej masie obiektów, a więc...

Gdybym miał mieć cały zestaw obiektów do utworzenia, gdzie każdy obiekt ma wspólną klasę-rodzica, to by to miało ręce i nogi, ale tak to tylko zapaskudzę kod i dołożę sobie masę roboty.

Zatem nie rozumiesz jak fabryka może działać.
Ale to chyba nie o to tu chodzi....

Tutaj potrzeba czegoś na kształt callbacków, aby uniknąć implementowania logiki dotyczącej interakcji z użytkownikiem wewnątrz klas z danymi.

Tylko po co ta cała interakcja z userem podczas ładowania konfiguracji?

Ewentualnie coś w formie zdarzeń wstrzykiwanych z zewnątrz.

Przecież zdarzenia z definicji są "wstrzykiwane" z zewnątrz.
Nie wiem dokładnie jak to wygląda, ale raczej zrobiłbym to na obserwatorach lub delegatach.

I na pewno nie na sztandarowych zdarzeniach.

0
wloochacz napisał(a):

Czym innym jest pominięcie brakującej danej podczas odczytu i nie jest to sytuacja krytyczna, a czym innym brak istotnych danych dla aplikacji.

Te przypadki odróżnia jedynie sposób interakcji z użytkownikiem – albo daję mu wybór, albo tylko informuję.

To pierwsze to na pewno nie wyjątek raczej ostrzeżenie do logu.
To drugie, to zawsze wyjątek.

Są trzy ogólne przypadki, które należy respektować:

  1. Brakuje mało istotnych danych i mogą one być resetowane (użycie konfiguracji domyślnej). Użytkownik nie musi wiedzieć, że czegoś program nie był w stanie ”określić” lub warunki środowiskowe się zmieniły i program musi się do nich dostosować. Info co najwyżej leci do logu i to wszystko.

  2. Brakuje istotnych danych, ale możliwa jest kontynuacja rozruchu. Program będzie działał stabilnie i przewidywalnie, ale użytkownik będzie musiał sobie coś od nowa ustawić, bo zostaną załadowane ustawienia domyślne, a na koniec sesji wadliwy plik zostanie nadpisany prawidłowymi danymi. Użytkownik dostaje komunikat ostrzeżenia/błędu i ma wybór co robić.

  3. Brakuje krytycznych danych, bez których program nie będzie w stanie działać prawidłowo. W takim przypadku kontynuacja rozruchu nie jest możliwa, więc użytkownik dostaje komunikat błędu, po zamknięciu którego program się wyłącza.

I po trzecie - moim zdaniem, możesz całkowicie pominąć kwestie związane z powiadamianiem i oczekiwaniem decyzji od użytkownika.

Mogę, ale nie chcę. Użytkownik po pierwsze musi dostać w twarz szczegółowym komunikatem błędu i musi mieć możliwość wyboru co robić. Takie mam wymagania, które dla mnie są logiczne i których wdrożenie pozwoli traktować użytkownika jak człowieka. ;)

A tak na poważnie – nie mam tutaj na myśli jakichś molochowych systemów, do których naprawy potrzeba wykwalifikowanego serwisanta analizującego logi i stacktrace, a raczej relatywnie małe projekty – np. coś pokroju Inkscape. Nie wyobrażam sobie, aby po wystąpieniu błędu program po cichu zamykał się, bez jawnego informowania użytkownika o problemie, nawet jeśli ów użytkownik i tak nie będzie w stanie samemu naprawić problemu.

Nawet jeśli dostarczysz mechanizm który będzie zbierał feedback od usera to i tak najprawdopodobniej będzie on (feedback, nie mechanizm) nieprawidłowy.

To brzmi jakby problem nie posiadał dobrego rozwiązania. A jest on raczej powszechny. Masa narzędzi użytkowych ma tego typu funkcjonalność i powiadamia użytkownika komunikatami błędów – dzięki temu wiadomo co jest nie tak i można sobie szybko wygooglać rozwiązanie, bez analizy logów czy posiadania jakiejkolwiek specjalistycznej wiedzy.

Rozwiązanie nie musi być wybitne – ma być proste w implementacji, skuteczne i łatwe w utrzymaniu. Tylko tyle (a może aż tyle).

Wg mnie lepiej całkowicie darować sobie moment czekania na decyzję usera. A może i nawet powiadamiania... […] Ano dlatego, że najpewniej user w przypadku problemu i tak nic z nim nie zrobi lub robi źle.

Ale przynajmniej zawsze dowie się w czym problem.

O ile Ty będziesz userem, to pewnie będziesz w stanie ocenić czy brak jakiejś konfiguracji jest krytyczny i nie można jej pominąć lub nie.

Po to właśnie chcę wyświetlić komunikat, w którym jasno i szczegółowo przedstawi się sprawę. Nie mam tutaj na myśli elaboratu, a krótki i merytoryczny komunikat pokroju: „Program nie był w stanie załadować pliku ”foo/bar/xyz” – plik ten nie istnieje na dysku lub jest uszkodzony. W celu naprawy danych programu zrób to i to i spróbuj ponownie.” I od razu wiadomo, że użytkownik powinien np. odpalić instalator i wybrać opcję naprawy, aby móc poprawnie uruchomić aplikację.

Poza tym, co to za informacja "nie udało się załadować XYZ czy kontynuować"?

Zgadzam się, ale to nie jest szczegółowy opis problemu. ;)

wloochacz napisał(a):

Dlaczego jeden obiekt?
Sam pisałeś o całej masie obiektów, a więc...

Co prawda klas jest kilkadziesiąt, ale w większości są to klasy niepowiązane ze sobą dziedziczeniem. Są też np. listy obrazów – tam masą obiektów są po prostu obrazy, wpakowane do jednej mapy generycznej.

Zatem nie rozumiesz jak fabryka może działać.

Racja – nie rozumiem, nie rozumiem sensu jej implementacji w moim przypadku. Wydaje się, że nakład pracy będzie niewspółmiernie duży w stosunku do zyskanych korzyści.

Tylko po co ta cała interakcja z userem podczas ładowania konfiguracji?

Konfig to tylko uproszczenie na potrzeby zilustrowania problemu. Ogólnie zależy mi na tym, aby o każdym krytycznym lub wartym uwagi problemie użytkownik się dowiedział, bez względu na to czy sam może coś poradzić czy nie.

0

Dokładnie nad podobnym rzeczą się zastanawiałem. Gdy podczas rozruchu aplikacji ta łączyła się z serwerem dostawcy, ładowała piliki, dll itd.

Ja to rozwiązałem tak że wszystkie klasy oparłam na własnej klasie bazowej która podczas tworzenia, tworzyła wątek który to weryfikował jak długo klasa istnieje (stoper który generował wyjątek jak klasa nie zwolni się w ciągu np 5 sekund lub nie wykona procedury potwierdzające np UkończonoPowodzeniem; Wszystkie wyjątki programu kierowałem do własnego przechwytywania i tam wiedziałam która klasa wygenerowała wyjątek i co zrobić dalej. Jeżeli chciałem wrócić dalej do wykonywania to używałem wstawki z assemblera który robił nic innego jak polecenie goto w Destructor klasy która wygenerowała wyjątek i kod leciał dalej.

Może nie jest to najlepsze rozwiązanie ale działało :)

0
Rafał D napisał(a):

Ja to rozwiązałem tak że wszystkie klasy oparłam na własnej klasie bazowej która podczas tworzenia, tworzyła wątek który to weryfikował jak długo klasa istnieje […]

To brzmi na overkill – czegoś takiego jak timeout nie było, że aż wątki pilnujące trzeba było tworzyć?

Jeżeli chciałem wrócić dalej do wykonywania to używałem wstawki z assemblera który robił nic innego jak polecenie goto w Destructor klasy która wygenerowała wyjątek i kod leciał dalej.

Assemblerem? Do destruktora?! Szacun. :D


Ogólnie chodzi o bardzo prostą rzecz, czyli oparcie całego procesu ładowania/zapisu danych na jednej logicznej/enumowej fladze (podawanej do każdej klasy ładującej/zapisującej) oraz zestawie zdarzeń obsługujących interakcję z użytkownikiem i manipulowanie wartością wspomnianej flagi. W ten sposób będzie można łatwo przerwać cały proces, a także podłączyć sobie odpowiedni zestaw zdarzeń pod dany proces (dla ładowania jeden, dla zapisu inny). Nie trzeba zbyt wiele kodu pisać.

Powoli szlifuję małego PoC-a, w którym szlifuję docelowe rozwiązanie. Jak go doszlifuję to podrzucę go tutaj.

0

Wiem czasami mam szalone pomysły :) Już się o tym dowiedziałem na tym forum.

A tak na poważnie może Ci się to przyda. Komponenty Clever suite maja ciekawa rzecz która nie wiem jak dziala:) nie mam ich z kodem źródłowym.

Mamy taką procedurę

Procedurę tform1.button1;
Begin
    Label1.caption := 'start
    Clftp1.put(filename);
    Label2.caption := 'koniec
End;

Klikamy przycisk i plik jest wysyłany na serwer i jak to wyśle to napis zmienia tekst. Niby nic szczególnego poza tym że po wykonaniu procedury put. Program się odmraża. Można klikać inne przyciski na formie wykonywać inny kod inne funkcje. Nawet zamknąć formę ale ta się zamknie gdy plik zostanie wysłany i label zmieni wartość.

Nie mam pojęcia jak to zrobili że program główny wykonuje czesc procedury potem można inne wykonywać A w między czasie po wysłaniu pliku wraca do wykonywania dalszej części kodu.

Tu nie wystarczy choćby application.processmessages;

0
Rafał D napisał(a):

Nie mam pojęcia jak to zrobili że program główny wykonuje czesc procedury potem można inne wykonywać A w między czasie po wysłaniu pliku wraca do wykonywania dalszej części kodu.

Zwykły wątek poboczny – dzięki temu główny wątek (ten dla UI) zostaje natychmiast odblokowany, dzięki czemu kolejka komunikatów jest przetwarzana bez opóźnień, co zapobiega zamrażaniu programu i zmuszaniu użytkownika do czekania, aż proces wysyłania zostanie zakończony.

Tu nie wystarczy choćby application.processmessages;

Application.ProcessMessages przeznaczony jest głównie dla aplikacji jednowątkowych, po to by móc przetwarzać kolejkę komunikatów podczas gdy wykonywane są operacje trwające dość długo. Dzięki temu można np. aktualizować interfejs po każdym ”kroku” wykonanym przez długo działający algorytm oraz w międzyczasie odbierać input użytkownika.

Należy jednak pamiętać, że tej metody nie powinno się stosować zamiast wątków pobocznych, bo ma spore ograniczenia. Jej usilne stosowanie potrafi nieźle napaskudzić w kodzie.

0
furious programming napisał(a):
Rafał D napisał(a):

Nie mam pojęcia jak to zrobili że program główny wykonuje czesc procedury potem można inne wykonywać A w między czasie po wysłaniu pliku wraca do wykonywania dalszej części kodu.

Zwykły wątek poboczny – dzięki temu główny wątek (ten dla UI) zostaje natychmiast odblokowany, dzięki czemu kolejka komunikatów jest przetwarzana bez opóźnień, co zapobiega zamrażaniu programu i zmuszaniu użytkownika do czekania, aż proces wysyłania zostanie zakończony.

Mówisz?
To pokaż mi proszę jak zrobić to na zwykłym wątku pobocznym coś takiego, że "program główny wykonuje czesc procedury potem można inne wykonywać A w między czasie po wysłaniu pliku wraca do wykonywania dalszej części kodu.".

To wygląda jak wątkowe ShowModal, z tym że takie wątkowe ShowModal nie zawiesza głównej pętli komunikatów dla aplikacji i pozwala jej normalnie pracować.
I równocześnie zawiesza kod metody, która go wywołała.
I nie, tego się nie da zrobić na samym wątku pobocznym, ponieważ on nie będzie zwieszał kodu, który go powołał do życia..
To jest odrobinę bardziej skomplikowane...

Wygląda to trochę jak async/await wbudowane w same komponenty Clever.

Tu nie wystarczy choćby application.processmessages;

Nie, nie wystarczy.

Application.ProcessMessages przeznaczony jest głównie dla aplikacji jednowątkowych, po to by móc przetwarzać kolejkę komunikatów podczas gdy wykonywane są operacje trwające dość długo. Dzięki temu można np. aktualizować interfejs po każdym ”kroku” wykonanym przez długo działający algorytm oraz w międzyczasie odbierać input użytkownika.

Należy jednak pamiętać, że tej metody nie powinno się stosować zamiast wątków pobocznych, bo ma spore ograniczenia. Jej usilne stosowanie potrafi nieźle napaskudzić w kodzie.

Moim zdaniem on to wie, ale Ty nie zrozumiałeś o czym @Rafał D pisze ;-)

0
wloochacz napisał(a):

To pokaż mi proszę jak zrobić to na zwykłym wątku pobocznym coś takiego, że "program główny wykonuje czesc procedury potem można inne wykonywać A w między czasie po wysłaniu pliku wraca do wykonywania dalszej części kodu.".

Hmm… faktycznie nie zrozumiałem. ;)

Wygląda mi to albo na coś pokroju free-pascalowego QueueAsyncCall, albo na jakiś trik związany ze stosem – trudno powiedzieć. Mimo wszystko nie spotkałem się jeszcze z czymś takim, więc jeśli ktoś zna szczegóły działania tych komponentów to z chęcią bym się z nimi zapoznał.

1 użytkowników online, w tym zalogowanych: 0, gości: 1