Gauge i odświerzenie z Wątku nie działa

0

Na **from1 **mam pasek postępu Gauge i przycisk button1

procedure TForm1.button1
var
  a : TWatek;
begin
  a := TWatek.Create(False);
  sleep(5000);
end;

**
Kod Watku**

var
  x : integer;

Procedure TWatek.Exceute;
begin
  for x:= 0 to 1000 do begin
    sleep(100);
    Synchronize(Gauge);
  end;
end;

Procedure TWatek.Gauge;
begin
  Form1.Gauge.Position := X;
  Form1.Gauge.Refresh / Repaint / Update / Paint;
end;
  
end;

Wątek odpala się od razu ale Gauge przesuwa się dopiero gdy przestanie się wykonywać program na form1. Czyli w tym przypadku Sleep(5000). Próbowałem także z poleceniami windows i wysyłałem komunikaty draw ale bezskutecznie. Ktoś ma jakiś pomysł jak rozwiązać ten problem (odświeżana może być cała forma) Application.ProcessMessages - jest trochę niebezpieczne

0

A gdzie zmieniasz w sposób prawidlowy Position tego Guage? A jeśłi już TGauge to chyba chodzi o Progress? Poczytaj o pętlach for i zasadach deklarowania zmiennych do iteracji. I ogólnie o wątkach. Poczytaj do czego służy Synchronize. I w ogóle jeżeli dobrze rozumiem ideę wątków, to takie operacje długo trwałe i mogące zatrzymać reagowanie formatki powinny wykonać się właśnie w nich, a nie w wątku głownym. Po to właśnie powstały wątki.

Poza tym, dlaczego uparcie pytania o banalne podstawy nie chcesz zadawać w dziale Newbie? Ponownie przenoszę, ale jeżeli nie będziesz chciał się zastosować do zasad i moich prósb, to mimo wszystko będę zmuszony uprzejmie przenosić takie wątki raczej do innego działu - Kosz :/ I radzę najpierw pogooglować, poczytać, pomyśleć, pokombinować samodzielnie, a nie ze wszystkim od razu "lecieć" na forum.

Oczywiscie wiem,. że forum jest od pomocy, ale trzeba je traktować jako ostateczność kiedy samodzielnie popróbowało się już wszystkiego. No i tak, wiem że wątki to temat rzeka, niekoniecznie dla początkujących, ale to o co pytasz wedle mnie nie zahacza o bardziej zaawanoswane rzeczy, nawet odnośnie wątków.

3

Nie da się nic zrobić bo masz sleep w głównym wątku aplikacji przez to żadne komunikaty nie są obsługiwane więc nie ma mowy o odświeżeniu okna lepiej napisz do czego ten sleep ma służyć to się wymyśli inne sensowne rozwiązanie.

0

Olesio zwrócę na to uwagę gdzie zamieszczam jakie posty.

Niestety przykłady które znalazłem na google nie za bardzo się sprawdzają. Zakładamy taką sytuację:

Na formie 1 mam przycisk i gauge. Klikam button. Ten wykonuje część kodu i tworzy wątek który coś tam wykonuje jednocześnie pokazując ile już wykonał w Gauge i kończy wątek.

I teraz program w procedurze onClick buttona czeka na zakończenie wątku, jak czeka to zawiesza program bo sprawdza czy wątek się zakończył jeśli tak to wykonuje kod dalej.

Cały problem polega na tym żę Gauge które używam jest animowane (czyli jeśli Progress stoi w miejscu to i tak co chwile przelatuje przezniego "swiatełko") chybą ze form1 jest czymś zajęte (np sleep, lub czekaniem na zakończenie wątku) to wtedy animacja umiera. Sprawdzałem ten komponent i jest on zrobiony na timer-ze.

Ja widzę takie rozwiązanie chyba że macie lepsze pomysły.

Button1 -> klikam wykonuje pierwszą cześć kodu , tworzą wątek, form1.enabled ustawiam na False;
Wątek wykonuje z działającym Gauge bo forma nie jest niczym zajęta
Wątek się kończy i w onTerminate uruchamia procedurę która kontynuuje to co rozpoczął Button1.
form1.Enabled := True;

0

Chyba duzo lepszym rozwiązaniem bedzie wysyłanie własnego komunikatu do wątku głownego (naszej aplikacji o tym iż zakończył działanie)

  1. Klikam button1 na form1 który wykonuje pierwszą cześć kodu i tworzy wątek A.
  2. Gdy wątek się kończy wysyła komunikat:
 PostMessage(Form1.Handle, WM_USER+500, 0, 0);
  1. Ten komunikat odbiera Form1
procedure Test(var Msg: TMessage); message WM_USER+500;

i wykonuje procedurę kończocą to co rozpoczął button1.

Wszystko działa idealnie łącznie z Gauge ale mam pewien problem.

Po tym jak kliknę button1 to wszystkie 3 pozycje powyżej muszą zostać wykonane bez jakichkolwiek zmian na form1. A teraz gdy program wykona punkt 1. to w czasie wykonywania punktu 2 mogę grzebać po formie. Pytanie jak to sensownie zablokować?

0

Rozpisałem się, ale w jednym zdaniu - tak to będzie najlepsze rozwiązanie. Wywal tego form1.Enabled := True/false i repaint bo bez tego wszystko powinno być ok

0

@Rafał D: spoko, ale z tym wysylaniem komunikatu zupełnie niepotrzebnie kombinujesz. Daj po prostu operacje czasochłonne "do środka" wątku. Bo od tego jest wątek poboczny, aby nie wstrzymywać działania formatki przez na przykład Sleep w wątku głownym. Czyli zastosuj się do porad, które udzielili tutaj @kAzek i teraz @szopenfx. A i zmienna dla pętli powinna być oczywiście lokalna i jeśli już musisz tak kombinować - imo ponownie niezbyt dobrze - że to X ma przyjąć wartość iteratora pętli to ustawiaj ową zmienną w tejże pętli. Chociaż tutaj całe to kombinowanie jest jak rozumiem dla przykładu, ale i tak robisz to niezbyt prawidłowo.

0

Po mojemu to nie trzeba jakoś udziwniać zwykła pętla z Application.ProcessMessages powinna dobrze działać i raczej nie ma nic złego w "szatańskim" Application.ProcessMessages

while WaitForSingleObject(Watek.Handle, 100) = WAIT_TIMEOUT do
    Application.ProcessMessages;

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