konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Witam,

zna ktoś może sposób jak zapobiec temu zjawisku gdy np wykonywane jest duże zapytanie i trwa np 30 sek. to postgres.exe zajmuje procka.. no i forma wisi.

Jeśli ktoś zasugeruje wątki - to które działanie ma być w którym wątku ? bo pewne próby robiłem i nic nie pomogło..Wojtek Stępień edytował(a) ten post dnia 03.09.10 o godzinie 11:21

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Jeżeli to zjawisko spowodowane jest np. działaniem pętli to stosuje się w niej instrukcję:

Application.ProcessMessages;

Wtedy mogę wykonywać inne operacje np. kliknięcie na jakiś przycisk podczas działania pętli (np. zatrzymanie pętli).

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Znam tą metodę ale to w tej sytuacji nie pomaga.
Sytuacja o którą pytam to jest wywołanie select moja_funkcja w komponencie TZQuery,
gdzie moja funkcja wykonuje sporo operacji i troche trwa.. Podczas wykonywania tego zapytania forma się zawiesza na czas jego trwania.
Robert W.

Robert W. Programista

Temat: Zamrażanie formy podczas wykonywania dużego...

Witam,

Borykałem się już kiedyś z takim problemem. W efekcie powstała klasa, która wykonuje zapytanie w osobnym wątku. Wg mojej opinii (zapewne subiektywnej ;)) jest całkiem przyzwoita w użyciu. Powstała na potrzeby konkretnego projektu, ale udało mi się ją jakość "uogólnić" aby była w miarę jak najbardziej elastyczna.

Jeżeli jesteś zainteresowany mogę Ci ją podesłać. Z tym, że przystosowana jest do ADO, ale przerobienie na ZEOS nie będzie stanowiło większego wyzwania :)

Pozdrawiam,
Robert

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Myślę, że to poniżej będzie bardzo pomocne (TZQuery + wątki):

http://lazarus.firmos.at/index.php?topic=4444.0

Mała uwaga: rozwiązanie napisane w tamtym wątku może nie działać ze względu na to, że odpala kilka zapytań równolegle, dla jednego zapytania nie powinno być problemów.Piotr Likus edytował(a) ten post dnia 04.09.10 o godzinie 00:29

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Spróbowałem, otwieram niby TZQuery w wątku..ale i tak forma wisi..w tym czasie..

może dlatego ze serwer postgresql działa lokalnie?Wojtek Stępień edytował(a) ten post dnia 05.09.10 o godzinie 01:06
Krzysztof Dibowski

Krzysztof Dibowski Programista Delphi /
Lazarus Free Pascal

Temat: Zamrażanie formy podczas wykonywania dużego...

Może robisz Open na query w synchronizowanej metodzie wątka? Wtedy zapytanie i tak jest wykonywane przez główny wątek aplikacji więc nic to nie zmienia. Ważne jest aby Open wołać bezpośrednio w procedurze TThread.Execute lub w innej "niesynchronizowanej" procedurze wołanej przez Execute.

Kiedyś miałem podobny problem i w skrócie rozwiązałem go tak:

1. Przed odświeżeniem grida odpinam od niego datasource (jeszcze przed uruchomieniem wątka)
2. Odpalam wątek i w execute wołam Open na query.
3. Zaraz po Query.Open podpinałem ponownie datasourca do grida aby wyświetlić wynik poprzez Synchronize(ProceduraPodpinajacaGrida)

Uwagi:
We wszystkich tutorialach o wątkowaniu zapytań do bazy jakie czytałem, jest napisane, że jeżeli wykonujemy zapytanie w wątku to ów query powinno mieć własne osobne połączenie z bazą danych w ramach tego wątka. Mimo wszystko powyższy sposób mi działał ale pewnie dlatego, że w trakcie tego zapytania nie wykonywałem żadnych dodatkowych zapytań w głównej aplikacji. Podejrzewam, że jeżeli wykona się dodatkowe zapytanie do bazy w głównym wątku jeżeli trwa pobieranie danych w wątku pobocznym to dojdzie do zakleszczenia (oba skorzystają z tego samego połączenia) i aplikacja się wywali.

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Masz racje tak robiłem (Open w synchronizowanej :)), sprawdzę to jeszcze

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Dzięki za odpowiedzi, poradziłem już sobie;) Wydaje się, że działa OK.

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Jednak nie do konca ;)

Chodzi o to ze pierwsze użycie i jest wszystko ok ale bez zamykania formy znowu chce zrobic to samo..i cos jest nie tak.. nie wykonuje sie itd..a powinien sie stworzyc od poczatku skoro mam w Execute:

FreeOnTerminate:=True;

?

Coś się krzaczy z połączeniem z bazą tak mi sie wydaje.. zwraca wyjatek "Can't open resultset" A ja zamykam to TZQuery zanim go otworze za pomocą watku..

Jakiś pomysł? sugestia ?:)Wojtek Stępień edytował(a) ten post dnia 05.09.10 o godzinie 17:33
Piotr M.

Piotr M. programista

Temat: Zamrażanie formy podczas wykonywania dużego...

Czy ekstra połączenie dla tego wątku tworzysz w jego Execute czy tylko sobie zrobiłeś ten wątek do zrobienia query.open() na boku, a resztą się nie przejmujesz?

Przy okazji, do synchronizacji zamiast "Synchronize(procka)" polecam AsyncCalls
EnterMainThread;
try
...
finally
LeaveMainThread;
end;

albo (od D2009)
TThread.Synchronize|Queue(nil, procedure begin ... end);
Piotr F. edytował(a) ten post dnia 05.09.10 o godzinie 19:16

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Tzn to wygląda w ten sposób (pewnie nie za dobrze ;)):

type
TOpenQuery=class(TThread)
private
FQuery:TZQuery;
procedure MyQuery;
procedure MyQueryClose;
protected
procedure Execute; override;
public
constructor Create(Q:TZQuery);
end;



constructor TOpenQuery.Create(Q:TZQuery);
begin
inherited Create(True);
FQuery:=Q;
FreeOnTerminate:=True;
Resume;
end;

procedure TOpenQuery.Execute;
begin
try
MyQueryClose;
FQuery.Open;
Synchronize(MyQuery);
except on e:Exception do
FRes:=True;
end;
end;

procedure TOpenQuery.MyQuery;
begin
FRes:=FQuery['export'];
end;

procedure TOpenQuery.MyQueryClose;
begin
If FQuery.Active Then FQuery.Close;
FRes:=False;
end;



a w jednej z procedur :


TOpenQuery.Create(DMExpIBank.QExport);
While not FRes do begin
Application.ProcessMessages;
end;


podejrzewam, że to nie jest tak jak powinno być :) natomiast za 1 razem użycia wszystko jest OK. Zadnych wyjątkow , wynik taki jaki być powinienWojtek Stępień edytował(a) ten post dnia 05.09.10 o godzinie 21:34
Piotr M.

Piotr M. programista

Temat: Zamrażanie formy podczas wykonywania dużego...

Query i połączenie powinieneś mieć tworzone w Execute() wątku. I to w zasadzie cała filozofia. A druga sprawa, unikałbym jakichkolwiek pętelek z Application.ProcessMessages, bo tego typu rozwiązania lubią się później odbijać dużą czkawką, zwłaszcza przy zamykaniu programu. Można to przecież zrobić elegancko na eventach.

Zwróciłeś w ogóle uwagę na to, że ta pętelka wcina Ci jeden rdzeń procka?
Programowanie w Delphi jest proste do czasu aż ludzie biorą się za wątki...Piotr F. edytował(a) ten post dnia 05.09.10 o godzinie 21:58

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

W sumie usunąłem jedną procedurę która zamykała(już to wcześniej robię) zapytanie i działa juz OK.(kilkakrotne wywolanie nie powoduje bledow i wszystko jest niby tak jak chce)

Ja na czas wykonywania tej petli nie robie nic innego.. nawet forma jest Enabled:=False;

Jak mogę to zastąpić?

chodzi o to ze musze poczekać na zakonczenie wątku w procedurze ale w tym czasie nie chce mieć zawieszonej formy..a niestety mam.. mimo ze Open dla TQuery jest w wątku i nie mam teraz zadnego synchronize.Wojtek Stępień edytował(a) ten post dnia 06.09.10 o godzinie 01:57
Piotr M.

Piotr M. programista

Temat: Zamrażanie formy podczas wykonywania dużego...

Query i połączenie powinieneś mieć tworzone w Execute() wątku. Zapamiętaj to jak AMEN W PACIERZU. To że działa to może być najwyżej dowód na to, że kiepsko wytestowałeś, albo że Ci się spieszy bo już jest wrzesień.

Powtórzę też:
Zwróciłeś w ogóle uwagę na to, że ta pętelka wcina Ci jeden rdzeń procka?
W autostarcie powinieneś mieć obowiązkowo ładowane:
http://technet.microsoft.com/en-us/sysinternals/bb8966...


type
TMojaProckaInformujacaOZakonczeniuQuery = procedure ( AQuery : TQuery ) of object;

TMojWatek = class(TThread)
protected
FKoniecQuery : TMojaProckaInformujacaOZakonczeniuQuery;
public
constructor Create( ...; AKoniecQuery : TMojaProckaInformujacaOZakonczeniuQuery );
//w srodku FKoniecQuery := AKoniecQuery;
end;

procedure TMojWatek.Execute;
begin
//utworzenie query i polaczenia
//query.open
if Assigned(FKoniecQuery) then
begin
EnterMainThread;
try
FKoniecQuery(query);
finally
LeaveMainThread;
end;
end;
end;

TMojaFormatka = class(TForm)
procedure KoniecQuery( AQuery : TQuery );
end;

procedure TMojaFormatka.KoniecQuery( AQuery : TQuery );
begin
//zapiecie query
end;

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

1. To nie jest do szkoły. To moje własne próby na moje potrzeby.
2. Tak zwróciłem uwagę. Jak mogę poczekać na zakończenie wątku w innej procedurze/funkcji(W tej w której go wywołałem) bo do dalszego działania potrzebny mi jest true z tego zapytania które wywołuje w wątku?

pisząc połączenie masz na myśli połączenie do bazy ?
Piotr M.

Piotr M. programista

Temat: Zamrażanie formy podczas wykonywania dużego...

Wojtek Stępień:
2. Tak zwróciłem uwagę. Jak mogę poczekać na zakończenie wątku w innej procedurze/funkcji(W tej w której go wywołałem) bo do dalszego działania potrzebny mi jest true z tego zapytania które wywołuje w wątku?

Musisz się nauczyć programowania opartego o zdarzenia, a nie klepać kod, który wykorzystuje główny wątek do czekania na cokolwiek w pętli. Zapomnij o takich rozwiązaniach jeśli chcesz zrobić jakikolwiek krok do przodu.

Przedstawiłem Ci przykładowy schemat wyżej. Inne i prostsze rozwiązanie to użycie timera.

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

Ok sprawdzę to.

konto usunięte

Temat: Zamrażanie formy podczas wykonywania dużego...

hmm próbowałem i tego i WaitForSingleObject.. faktycznie wyeliminowanie tej petli odciaza procka.. ale nie do końca zrobiłem to tak jakbym chciał. Nie mam trochę czasu teraz na dokładne anlizowanie tego.

Dziękuje wszystkim za pomoc.
Pozdrawiam
Piotr M.

Piotr M. programista

Temat: Zamrażanie formy podczas wykonywania dużego...

Tak na prawdę obciążenie procka to najmniejszy problem, bo wystarczy dać Sleepa...

Następna dyskusja:

Turbo Delphi 2006 (v. 10) ...




Wyślij zaproszenie do