pawel24pl:
Application.ProcessMessages przy bardzo szybkim kliknięciu dwóch przycisków mających za zadanie modyfikować np: tą samą zmienną globalną, może dojść do błędu [...]
No może dojść do błędu, ale to nie zmienia faktu, że jak się używa tej metody w sposób odpowiedzialny i prawidłowy to do błędu nie doprowadzi...
W swoim projekcie mam animowany slider do zakładek, który wykorzystuje Application.ProcessMessages
podczas animacji; Po kliknięciu innej zakładki niż aktywna, zakładki przełączają się, slider startuje i jedzie do tej przed chwilą aktywowanej; Po każdym skoku slidera o 1px
wywoływana jest ta metoda, aby oblokować m.in. czekający w kolejce komunikat REPAINT
, czyli aby po skoku slidera, suwak ten został przemalowany; Jak nie wywołam tej metody, suwak nie będzie jechał - zostanie przemalowany jedynie po skończeniu animacji, czyli po prostu zniknie z początkowej pozycji i od razu pokaże się na końcowej;
Kod metody animującej suwak wrzuciłem tutaj - https://4programmers.net/Pastebin/6292 - zobacz sobie;
Dzięki tej metodzie, animacja jest widoczna na ekranie, a podczas jej trwania przetwarzane są wszystkie inne komunikaty; Dzięki temu podczas jej trwania np. podświetlane są inne kontrolki po najechaniu kursorem, można zamknąć formularz (i nic się złego nie stanie), można odpalać zdarzenia spod innych komponentów itd. itd.;
Jak widzisz nie jest taka zła i nieprzydatna;
A trzeba wziąć pod uwagę, że samo Application.ProcessMessages opóźnia algorytm.
Bo po to została stworzona;
Problem pytającego polega na tym, że Timer nigdy nie osiągnie interwału 1 ms (ale to chyba już wyjaśnione) [...]
Tak, nigdy nie osiągnie takiej dokładności, bo używa zegara, który ma o wiele gorszą dokładność; Na poprzednim laptopie osiągałem minimum ~10ms
, a na tym co mam obecnie i drugim domowym, około 16ms
; Rozdzielczość pracy najpewniej zależna jest od sprzętowego zegara, ale mogę się mylić;
[...] oraz Application.ProcessMessages zajmuje (akurat u mnie) ok. 10 ms), co dodatkowo burzy działanie takiego algorytmu.
Obliczanie czasu działania tej metody nie ma żadnego sensu, bo kolejka komunikatów może być pusta i wykona się w mgnieniu oka, jak również może się w niej znajdować mnóstwo komunikatów, które zostaną obsłużone w kilka sekund; Poza tym robisz drugi poważny błąd, jeśli czas trwania tej metody mierzysz np. za pomocą GetTickCount
, która to jest równie niedokładna jak Sleep
czy TTimer
, bo te wszystkie elementy korzystają z tego samego, niedokładnego zegara;
A TTimer co jakiś czas, mimo opóźnień wywołuję procedurę jeszcze raz.
Nie można komparować metody ProcessMessages
z klasą TTimer
, bo ich przeznaczenie jest zupełnie inne; Metoda ta służy do przetworzenia oczekujących komunikatów, a wspomniana klasa do cyklicznego wykonywania kodu w ramach tego samego wątku;
To tak jakbyś powiedział, że rower jest lepszym środkiem stransportu, bo żeliwny kaloryfer słabiej grzeje;
Crow:
Niestety brnąc w to danej (konkretniej przy próbach usunięcia screen tearingu i flickeringu) odkryłem, że to po prostu nie ma większego sensu.
Według tego co wiem, rozrywania ekranu nie dasz rady wykluczyć po stronie aplikacji;
Delphi jest mało wydajny w renderowaniu grafiki i sprawia masę problemów.
Ale to nie Delphi jest temu winne, a tryb, w którym Twoja aplikacja działa i komponenty, których używasz;
Już wolę przerzucić się na C++ (ucząc się go od podstaw, bo nie miałem z nim wcześniej styczności) i biblioteki OpenGL czy DirectX, niż męczyć się dalej z Delphi. Tak wiem, Delphi też obsługuje te biblioteki, ale wyraźnie nie jest do tego stworzony.
Nie ma to żadnego logicznego podłoża - dokładnie ten sam problem będziesz miał, jeśli napiszesz aplikację w C++, która to będzie działać w trybie okienkowym i używać zwykłych komponentów; Dobry (a nawet idealny) efekt uzyskasz korzystając z Direct Draw, OpenGL czy DirectX, bez względu na język i środowisko programistyczne.