W▒tki

Strona g│≤wna

 

W▒tki

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