-
Kdy₧ ji₧ mßme implementovßny t°φdy vlßken metodou Execute, m∙₧eme
je pou₧φt v naÜφ aplikaci spuÜt∞nφm k≤du v metod∞ Execute. K pou₧itφ
vlßkna, nejprve vytvo°φme instanci t°φdy vlßkna. Instanci vlßkna m∙₧eme
vytvo°it tak, ₧e je spuÜt∞no bezprost°edn∞ nebo jej vytvo°φme v klidovΘm
stavu, kterΘ pozd∞ji spustφme volßnφm metody Resume. Pro vytvo°enφ
vlßkna s bezprost°ednφm spuÜt∞nφm p°edßme konstruktoru parametr
false.
Nap°. nßsledujφcφ °ßdek vytvß°φ vlßkno a spouÜtφ jeho provßd∞nφ:
TMyThread *SecondProcess
= new TMyThread(false); // vytvo°enφ a spuÜt∞nφ
Nevytvß°ejte ve svΘ aplikaci mnoho vlßken. DoporuΦen² limit je 16 vlßken
na proces v jednoprocesorovΘm systΘmu. Tento limit p°edpoklßdß, ₧e v∞tÜina
t∞chto vlßken bude Φekat na externφ udßlosti. Pokud vÜechna vlßkna jsou
aktivnφ, pak jich je mo₧no pou₧φt mΘn∞.
M∙₧eme vytvo°it vφce instancφ stejnΘho typu vlßkna pro provßd∞nφ paralelnφho
k≤du. Nap°. m∙₧eme vytvo°it novou instanci vlßkna v reakci na n∞jakou akci
u₧ivatele umo₧≥ujφcφ ka₧dΘmu vlßknu zpracovßvat oΦekßvanou reakci.
Mno₧stvφ Φasu CPU v∞novanΘ vlßknu je urΦeno nastavenφm priority v konstruktoru.
M∙₧eme takΘ vytvo°it vlßkno v klidovΘm stavu a nastavit prioritu a₧ p°ed
jeho spuÜt∞nφm:
TMyThread *SecondProcess
= new TMyThread(true);// vytvo°enφ bez spuÜt∞nφ
SecondProcess->Priority
= tpLower; // nastavenφ priority
SecondProcess->Resume();
// spuÜt∞nφ vlßkna
Vlßkna mohou b²t spouÜt∞na a zastavovßna n∞kolikrßt p°ed dokonΦenφm
provßd∞nφ. Zastavenφ vlßkna je doΦasnΘ a provedeme jej volßnφm metody Suspend.
Pro op∞tovnΘ spuÜt∞nφ volßme jeho metodu Resume. Suspend
inkrementuje internφ ΦφtaΦ, a tak m∙₧eme vno°ovat volßnφ Suspend
a Resume. Vlßkno nepokraΦuje v provßd∞nφ dokud vÜechny Suspend
nemajφ odpovφdajφcφ Resume.
K trvalΘmu ukonΦenφ vlßkna volßme metodu Terminate. Tato metoda
nastavuje vlastnost Terminated vlßkna na true. Pokud metoda
Execute
je sprßvn∞ implementovßna, je periodicky testovßna vlastnost
Terminated
a ukonΦuje provßd∞nφ, kdy₧ je true.
Kdy₧ naÜe aplikace vy₧aduje vφce instancφ stejnΘ t°φdy vlßkna (pro
opakovanΘ spouÜt∞nφ), pak m∙₧eme zv²Üit v²konnost odklßdßnφm vlßken pro
op∞tovnΘ pou₧itφ (namφsto jejich ruÜenφ a op∞tovnΘho vytvß°enφ). Pro odklßdßnφ
vlßken, musφme udr₧ovat seznam vytvo°en²ch vlßken. Tento seznam m∙₧e b²t
udr₧ovßn objektem, kter² pou₧φvß vlßkna nebo m∙₧eme pou₧φt globßlnφ prom∞nnou
k ulo₧enφ odlo₧enΘho vlßkna.
Kdy₧ je po₧adovßno novΘ vlßkno, pak je pou₧ito odlo₧enΘ vlßkno nebo
vytvo°eno novΘ vlßkno (viz nßsledujφcφ funkce):
TThreadList *pCache;
...
TThread *GetThread(void)
{
TList *pList
= pCache->LockList();
TThread *NewThread;
if (pList->Count)
// ₧ßdnΘ vlßkno nenφ odlo₧eno
{
NewThread = (TThread *)pList->Items[0];
pList->Delete(0); // odstran∞nφ ze seznamu
}
else
NewThread=(TThread *)new TMyThread(true);//vytvo°enφ ale nespuÜt∞nφ
pCache->UnlockList();
return NewThread;
}
Jestli₧e vlßkno konΦφ provßd∞nφ je odlo₧eno (obsluha OnTerminate):
void __fastcall TMyThread::Terminate(TObject
*Sender)
{
pCache->Add(&this);
}
Kdy₧ aplikace konΦφ provßd∞nφ (nebo objekt, kter² vlastnφ vlßkna je
ruÜen), pak odlo₧enß vlßkna musφ b²t uvoln∞na (obsluha OnDeactivate
aplikace):
void __fastcall TDataModule1::ApplicationDeactivate(TObject
*Sender)
{
TList *pList
= pCache->LockList();
for (int i
= pList->Count - 1; i >= 0; i--)
{
delete pList->Items[i];
pList->Delete(i);
}
pCache->UnlockList();
}
-
Pokud ladφme vφcevlßknovΘ aplikace, pak m∙₧eme sledovat
stav vÜech souΦasn∞ provßd∞n²ch vlßken nebo urΦit kterΘ vlßkno bude provßd∞no,
kdy₧ provßd∞nφ je zastaveno bodem p°eruÜenφ. M∙₧eme pou₧φt dialogovΘ okno
Stavu vlßken k manipulaci s vlßkny v naÜφ aplikaci. Toto okno zobrazφme
volbou View | Threads. Kdy₧ nastane ladφcφ udßlost (bod p°eruÜenφ,
provßd∞nφ) pak zobrazenφ stavu vlßkna indikuje stav ka₧dΘho vlßkna. V mφstnφ
nabφdce okna jsou volby k lokalizaci odpovφdajφcφho zdroje nebo k ud∞lßnφ
jinΘho vlßkna aktußlnφm. Jestli₧e vlßkno je oznaΦeno jako aktußlnφ, pak
nßsledujφcφ krok nebo operace je relativnφ k tomuto vlßknu. Vlßkna jsou
identifikovßna identifikaΦnφmi Φφsly (hodnota vlastnosti ThreadID).
-
Vrßtφme se k naÜφ aplikaci z p°edchozφ kapitoly.
Formulß° aplikace zv∞tÜφme a nastavφme u n∞j tyto vlastnosti: BorderStyle
na bsDialog a Caption na Demonstrace °azenφ. Na formulß°
p°idßme t°i komponenty Bevel a nastavφme u nich vlastnosti Top
na 24, Width na 177 a Height na 233.
U prvnφ z nich nastavφme Left na 8, u druhΘ na 192
a t°etφ na 376. Do ka₧dΘ z t∞chto komponent vlo₧φme komponentu PaintBox
a nastavφme u nich stejnΘ hodnoty vlastnostφ jako u komponent Bevel.
Levou z t∞chto komponent nazveme BubbleSortBox, prost°ednφ SelectionSortBox
a pravou QuickSortBox. Nad ka₧dou z t∞chto komponent vlo₧φme Label
s texty: Bublinkovß metoda, ╪azenφ v²b∞rem a Quick Sort.
Do spodnφ Φßsti formulß°e vlo₧φme jeÜt∞ tlaΦφtko s textem ZaΦni °adit.
Tφm je tento formulß° hotov. Do deklarace formulß°e vlo₧φme dalÜφ deklarace
(viz nßsledujφcφ v²pis hlaviΦkovΘho souboru formulß°e):
#ifndef ThSortH
#define ThSortH
#include <StdCtrls.hpp>
#include <ExtCtrls.hpp>
#include <Dialogs.hpp>
#include <Forms.hpp>
#include <Controls.hpp>
#include <Graphics.hpp>
#include <Classes.hpp>
#include <SysUtils.hpp>
#include <Messages.hpp>
#include <Windows.hpp>
#include <System.hpp>
class TThreadSortForm
: public TForm
{
__published:
TButton *StartBtn;
TPaintBox *BubbleSortBox;
TPaintBox *SelectionSortBox;
TPaintBox *QuickSortBox;
TLabel *Label1;
TBevel *Bevel1;
TBevel *Bevel2;
TBevel *Bevel3;
TLabel *Label2;
TLabel *Label3;
void __fastcall
BubbleSortBoxPaint(TObject *Sender);
void __fastcall
SelectionSortBoxPaint(TObject *Sender);
void __fastcall
QuickSortBoxPaint(TObject *Sender);
void __fastcall
FormCreate(TObject *Sender);
void __fastcall
StartBtnClick(TObject *Sender);
private:
int ThreadsRunning;
void __fastcall
RandomizeArrays(void);
void __fastcall
ThreadDone(TObject *Sender);
public:
void __fastcall
PaintArray(TPaintBox *Box,const int *A,
const int A_Size);
virtual __fastcall
TThreadSortForm(TComponent *Owner);
};
//--------------------------------------------------------------------
typedef int TSortArray[115];
typedef TSortArray
*PSortArray;
//--------------------------------------------------------------------
extern PACKAGE TThreadSortForm
*ThreadSortForm;
extern bool ArraysRandom;
extern int BubbleSortArray[115];
extern int SelectionSortArray[115];
extern int QuickSortArray[115];
#endif
Nßsleduje v²pis jednotky formulß°e:
#include <vcl.h>
#pragma hdrstop
#include <stdlib.h>
#include "thsort.h"
#include "sortthd.h"
#pragma resource
"*.dfm"
TThreadSortForm *ThreadSortForm;
//--------------------------------------------------------------
Boolean ArraysRandom;
TSortArray BubbleSortArray,
SelectionSortArray, QuickSortArray;
__fastcall TThreadSortForm::TThreadSortForm(TComponent
*Owner)
: TForm(Owner)
{
}
void __fastcall TThreadSortForm::PaintArray(TPaintBox
*Box,
int const *A, int const ASize)
{
int i;
TCanvas *canvas;
canvas = Box->Canvas;
canvas->Pen->Color
= clRed;
for (i=0;
i < ASize; i++)
PaintLine(canvas, i, A[i]);
}
//---------------------------------------------------------------
void __fastcall TThreadSortForm::BubbleSortBoxPaint(TObject
*)
{
PaintArray(BubbleSortBox,
EXISTINGARRAY(BubbleSortArray));
}
void __fastcall TThreadSortForm::SelectionSortBoxPaint(TObject
*)
{
PaintArray(SelectionSortBox,
EXISTINGARRAY(SelectionSortArray));
}
void __fastcall TThreadSortForm::QuickSortBoxPaint(TObject
* /*Sender*/)
{
PaintArray(QuickSortBox,
EXISTINGARRAY(QuickSortArray));
}
//---------------------------------------------------------------
void __fastcall TThreadSortForm::FormCreate(TObject
* /*Sender*/)
{
RandomizeArrays();
}
void __fastcall TThreadSortForm::StartBtnClick(TObject
* /*Sender*/)
{
TBubbleSort
*bubble;
TSelectionSort
*selsort;
TQuickSort
*qsort;
RandomizeArrays();
ThreadsRunning
= 3;
bubble = new
TBubbleSort(BubbleSortBox,
EXISTINGARRAY(BubbleSortArray));
bubble->OnTerminate
= ThreadDone;
selsort =
new TSelectionSort(SelectionSortBox,
EXISTINGARRAY(SelectionSortArray));
selsort->OnTerminate
= ThreadDone;
qsort = new
TQuickSort(QuickSortBox, EXISTINGARRAY(QuickSortArray));
qsort->OnTerminate
= ThreadDone;
StartBtn->Enabled
= False;
}
//---------------------------------------------------------------------
void __fastcall TThreadSortForm::RandomizeArrays()
{
int i;
if (! ArraysRandom)
{
Randomize();
for (i=0; i < ARRAYSIZE(BubbleSortArray); i++)
BubbleSortArray[i] = random(170);
memcpy(SelectionSortArray, BubbleSortArray,
sizeof(SelectionSortArray));
memcpy(QuickSortArray, BubbleSortArray, sizeof(QuickSortArray));
ArraysRandom = True;
Repaint();
}
}
//---------------------------------------------------------------------
void __fastcall TThreadSortForm::ThreadDone(TObject
* /*Sender*/)
{
ThreadsRunning--;
if (! ThreadsRunning)
{
StartBtn->Enabled = True;
StartBtn->SetFocus();
ArraysRandom = False;
}
}
Pokuste se podle tohoto v²pisu vytvo°it b∞₧φcφ
aplikaci a sna₧te se pochopit jednotlivΘ Φinnosti. Sna₧te se pochopit jak
pracujφ vφcevlßknovΘ aplikace.
-
P°idejte do p°edchozφ aplikace demonstraci dalÜφho
zp∙sobu °azenφ (vlßkno, kterΘ jste vytvo°ili na zßv∞r p°edchozφ kapitoly).