Home :: Artykuły :: Programowanie w Delphi :: Wielowątkowość w Delphi dla początkujących.

Logowanie



Dziękuję za wszelkie dotacje.

Kwota: 

Wielowątkowość w Delphi dla początkujących.
Wpisany przez Wojciech Romanek   
sobota, 16 lutego 2008 18:06

Pisząc programy w Delphi często mamy taką sytuację, że potrzebujemy wykonać jakieś skomplikowane obliczenia które zabierają dużo czasu, a przy okazji ich wykonywania blokowany jest cały program. Co zrobić aby program nie przestawał reagować na aktywność użytkownika? Najprostszy, aczkolwiek mało wydajny sposób to zastosowanie procedury:

Application.ProcessMessages;

Która to jest odpowiedzialna za odbieranie wiadomości. Do każdego programu w systemie Windows w trakcie działania programu wysyłane są różnego rodzaju wiadomośći odpowiedzialne np. za zamykanie programu, maksymalizację, minimalizację itp. Zadaniem tej funkcji jest odbieranie tych wiadomości. Pora na przykład. Utwórz nowy projekt w Delphi, na formę połóż przycisk (Button, zakładka Standard) oraz komponent ProgressBar (zakładka Win32). W zdarzeniu OnClick przycisku wpisz poniższy kod:

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
for i:=1 to 100 do
begin
ProgressBar1.Position:=ProgressBar1.Position+1;
Application.ProcessMessages;
Sleep(100);
end;
end;

Teraz uruchom program i spróbuj np przesówać formę itp. Wszystko działa ładnie. Jeśli chcesz zobaczyć jaka jest różnica bez używania funkcji Application.ProcessMessages; poprostu ją wykomentuj wstawiając przed nią dwa znaki "/. Jednak to rozwiązanie nie jest zbyt optymalne.

Lepszym rozwiązaniem jest zastosowanie wątków (ang. thread). Zmodyfikujemy teraz nasz program tak aby działał wykorzystując wątki. W Borland Delphi klikamy kolejno File \ New \ Thread. Pojawi się okienko takie jak poniżej w którym należy wpisać nazwę klasy. Ja wpisałem TWatek. Po zaakceptowania pojawia się nam kolejny unit. My z niego jednak nie będziemy korzystac, skopiujemy z niego tylko kod:

type
TWatek = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;

Który wstawimy zaraz po deklaracji typu TForm1. Kolejny fragment jaki skopiujemy z tego pliku to:

procedure TWatek.Execute;
begin
 
end;

Jest to procedura która będzie wykonywana w tym wątku. Ten fragment wklejamy w sekcji implementacji. Następnie deklarujemy zmienną globalną typu TWatek.

moj_watek:TWatek;

w zdażeniu formy OnCreate wpisujemy kod:

moj_watek:=TWatek.Create(true);

jest on odpowiedzialny za utworzenie wątku.Jeśli chcesz aby wątek uruchamiany był odrazu po jego utworzeniu jako parametr procedury TWatek.Create przekaż wartość false. Kiedy wartość parametru to true wątek zostanie wywołany dopiero po użyciu procedury Resume. W zdarzeniu OnDestroy wstawiamy  kod:

moj_watek.Terminate;

Odpowiedzialny za wyłączenie wątku.

Teraz wystarczy do procedury TWatek.Execute dodać kod który wcześniej użyliśmy w przycisku, tym razem jednak bez Application.ProcessMessages; dodatkowo przed nazwami komponentów VCL musimy dopisać Form1. Wygląda to tak:

for i:=1 to 100 do
begin
Form1.ProgressBar1.Position:=Form1.ProgressBar1.Position+1;
Sleep(100);
end;

a w zdarzeniu OnClick naszego przycisku:

moj_watek.Resume;

procedura ta uruchamia naszą funkcję zawartą w TWatek.Execute;. Teraz możemy uruchomić aplikację i przetestować jej działanie.