Co to w│a╢ciwie s▒ te w▒tki? Jest to oddzielny kod,
kt≤ry wykonuje jak▒╢ czynno╢µ. Wykonuje tΩ czynno╢µ niezale┐nie
od tego co siΩ z aplikacj▒ dzieje ( tzn., ┐e mo┐esz sw≤j formularz
przemieszczaµ, zmieniaµ rozmiary itp. ). Wyobra╝ sobie, ┐e program
wykonuje sobie jakie╢ obliczenia niezale┐nie od tego co robisz w danym
programie ( pisanie tekstu, obr≤bka grafiki ). W▒tki w│a╢nie tak
dzia│aj▒ - "w tle". Przyk│adem dzia│ania w▒tku jest
wpisywanie do kom≤rek arkuszu kalkulacyjnego warto╢ci i obliczenie np.
sumy.
Zaraz siΩ zreszt▒ o tym przekonasz.
Delphi udostΩpnia specjaln▒ klasΩ - TThread, kt≤ra
umo┐liwia zastosowanie wielow▒tkowo╢ci.
Utworzenie w▒tku to wybranie z menu File polecenia New, a nastΩpnie
pozycje Thread Object.
Delphi w≤wczas stworzy nowy modu│ z now▒ klas▒. Tak, tak, w▒tek to
nie ┐aden komponent tylko odrΩbna klasa. Tak wiΩc ┐eby stworzyµ w▒tek
nie wystarczy po│o┐yµ na formie komponent :) ale trzeba trochΩ
popisaµ. :) Nowy wygenerowany modu│ powinien wygl▒daµ tak:
TTest = class(TThread)
protected
procedure Execute; override;
end;
Ja zawsze wpisuje to rΩcznie do modu│u i ┐adko korzystam z tej mo┐liwo╢ci.
Ja akurat u┐y│em nazwy TTest. Polecam najpierw
poczytanie artyku│u "KLASY", aby
dowiedzieµ siΩ co╢ wiΩcej o klasach.
Jak wiΩc widzisz utworzona zosta│a nowa klasa
dziedzicz▒ca z innej - TThread. Klasa ta zawiera now▒ pozycjΩ w
sekcji protected.
Tak wiΩc kod, kt≤ry znajduje siΩ powy┐ej wpisz do
Twojego programu w sekcji Interface.
Uzupe│nij teraz w sekcji Implementation kod procedury
Execute:
uses Math;
procedure TTest.Execute;
var
I : Integer;
begin
FreeOnTerminate := True; // zakoncz watek po zaknczeniu tej procedury
for I := 1 to 1000 do
Power(I, I * 2);
end;
Zastosowanie tej procedury nie ma wiΩkszego sensu.
Podaje j▒ dla przyk│adu. Zwr≤µ uwagΩ na pierwsz▒ liniΩ tej
procedury. Powoduje ona zako±czenie w▒tku wraz z zako±czeniem tej
procedury. Masz ju┐ w▒tek - teraz trzeba go uruchomiµ:
procedure TForm1.Button1Click(Sender: TObject);
var
Test : TTest;
begin
Test := TTest.Create(FALSE);
end;
To powoduje uruchomienie w▒tku. Jako parametr wywo│ania
tego konstruktora wpisa│em FALSE co oznacza, ┐e w▒tek bΩdzie
automatycznie uruchamiany. Je┐eli w tym miejscu wpiszesz True to w▒tek
pozostanie w stanie "spoczynku", a jego wywo│anie spowoduje u┐ycie
polecenia:
Test.Resume;
Teraz co╢ trudniejszego - obliczenia ile czasu program
jest uruchomiony. Program bΩdzie posiada│ jen▒ etykietΩ ( lblCount )
oraz dwa przyciski typu TButton ( btnStart, btnStop ). Pierwszy z
przycisk≤w bΩdzie s│u┐y│ do rozpoczΩcia odliczania, a drugi do
zako±czenia.
Na pocz▒tek sama klasa:
TStoper = class(TThread)
private
Count : Integer;
protected
procedure Execute; override;
end;
W sekcji private znajduje siΩ zmienna, kt≤ra
przechowywaµ bΩdzie ilo╢µ sekund :) kt≤re up│ynΩ│y od czasu naci╢niΩcia
przycisku START. A wiΩc procedura Execute wygl▒daµ bΩdzie tak:
procedure TStoper.Execute;
begin
FreeOnTerminate := True;
while not (Application.Terminated) or (Terminated) do
begin
Sleep(1000);
Count := Succ(Count);
with MainForm do
lblCount.Caption := Format('Aplikacja uruchomiona: %d sekund.',
[Count]);
end;
end;
Procedura zawiera pΩtle, kt≤ra wykonywana bΩdzie dop≤ki program bΩdzie
dzia│a│ lub dop≤ki w▒tek bΩdzie w dzia│aniu. NastΩpnie pauza
trwaj▒ca jedn▒ sekundΩ ( Sleep ). PowiΩkszenie licznika ( zmienna
Count ) o jeden, a nastΩpnie wy╢wietlenie informacji na formie (
MainForm ).
TStoper = class(TThread)
private
Count : Integer;
protected
procedure Execute; override;
end;
var
MainForm: TMainForm;
Stoper : TStoper;
implementation
{$R *.DFM}
procedure TStoper.Execute;
begin
FreeOnTerminate := True;
while not (Application.Terminated) or (Terminated) do
begin
Sleep(1000);
Count := Succ(Count);
with MainForm do
lblCount.Caption := Format('Aplikacja uruchomiona: %d sekund.',
[Count]);
end;
end;
procedure TMainForm.btnStartClick(Sender: TObject);
begin
Stoper.Resume;
end;
procedure TMainForm.btnStopClick(Sender: TObject);
begin
Stoper.Suspend;
end;
initialization
Stoper := TStoper.Create(True);
end.
Jak zapewne siΩ domy╢li│e╢ dwa przyciski uruchamiaj▒ procedurΩ
Execute ( Resume ) lub zatrzymuje ( Suspend ). W sekcji "Initialization"
wpisane s▒ komendy, kt≤re maj▒ byµ wykonane w czasie gdy program bΩdzie
│adowany do pamiΩci komputera. W sekcji tej jest kod, kt≤ry powoduje
tworzenie nowego w▒tku. PΩtla bΩdzie wykonywana dop≤ty dop≤ki
aplikacja bΩdzie otwarta lub dop≤ki w▒tek bΩdzie uruchomiony.
Priorytet w▒tku
Istnieje mo┐liwo╢µ okre╢lenie priorytetu w▒tku. W zale┐no╢ci
od ustawionego priorytetu w▒tek nabierze innej "wa┐no╢ci" w
systemie :) Poni┐ej przedstawione s▒ dostΩpne priorytety:
- tpIdle
(
Ja│owy ) - jest to najni┐szy priorytet . W▒tek zostanie wykonany
tylko wtedy gdy inne aplikacje o wy┐szym priorytecie nie bΩd▒
potrzebowa│y wykorzystaµ procesora. Przyk│adem mog▒ byµ
wygaszacze ekranu, kt≤re posiadaj▒ w│a╢nie ten priorytet.
- tpNormal
(
Normalny ) - jest to domy╢lny priorytet przydzielany w▒tkom.
- tpHigher
(
Wysoki ) - nie nale┐y przydzielaµ tego priorytetu w▒tkom, kt≤re
wykonuj▒ jakie╢ skomplikowane obliczenia gdy┐ mo┐e to sparali┐owaµ
pracΩ systemu. Ten priorytet przydziela siΩ w▒tkom, kt≤re musz▒
otrzymaµ czas procedura natychmiast.
- tpTimeCritical ( Casu rzeczywistego )
- tego priorytetu u┐ywa siΩ bardzo rzadko - s│u┐y tylko do w▒tk≤w,
kt≤re wykonuj▒ kr≤tkie operacje i zaraz siΩ ko±cz▒. U┐ycie
tego w▒tku mo┐e siΩ wi▒zaµ z parali┐em systemu ( zawieszenie
myszki itp. ).
Nadawanie priorytetu nie jest niczym nadzwyczajnym - w powy┐szym
przyk│adzie powinno to wygl▒daµ tak:
Stoper.Priority := tpNormal;
Delphi udostΩpnie tak┐e odpowiednie wykorzystanie w▒tk≤w poprzez
WinAPI. Nie jest potrzebne w≤wczas stosowanie klasy Classes. Jest to
jednak nieco trudniejsze i na razie nie bΩdΩ na ten temat tutaj pisa│.
Mo┐esz o tym poczytaµ w systemie pomocy WinAPI Delphi pod has│em 'CreateThread'.
Jak widzisz w▒tki mog▒ siΩ przydaµ je┐eli chcemy, aby jakie╢
operacje by│y wykonywane jednocze╢nie z normalnym wykonywaniem
aplikacji.
Poni┐ej przedstawione s▒ przyk│ady wykorzystania wielow▒tkowo╢ci:
Watki.zip
( 3 kB ) - przyk│ad wykorzystania w▒tk≤w w rysowaniu;
Replace.zip
( 4 kB ) - autozastΩpowanie wyraz≤w - np: (c) na ©
Thread_tut.zip
( 220 kB )- rozbudowany przewodnik na temat w▒tk≤w (w. ang.).
Adam Boduch