Prev Next Up Title Contents Index

Säikeet ja dynaamiset kontrollit


Click here for Picture

Säikeet (=threads) eivät oikeastaan kuulu kieleen, vaan käyttöjärjestelmään. Koska Delphitoimii kuitenkin vain Windowsin alla, käsitellään tässä säikeet ikäänkuin kieleen kuuluvana asiana. Säikeet toimivat Win95:sta alkaen. Vertailukohdaksi otetaan Borland C++ 5.0, OWL 5.0 ja AppExpertillä osittain tehty sovellus.

Seuraava esimerkki luo dialogi- ikkunassa (lomakkeessa, form) valmiiksi olevan Käynnistä- näppäimen lisäksi joukon laskureita (Delphissä tekstikenttiä ja C++:ssa Tbutton- nappuloita). Kun Käynnistä- nappia painetaan, käynnistetään kutakin laskuri- kenttää varten oma prosessi (säie), joka pyörittää kentässä lukuja 0:sta ylöspäin. Kenttää painamalla voidaan ko. säie "tappaa". Kummastakin ohjelmasta on jätetty listaamatta sekä pääohjelma että resurssitiedosto.

saie\saiedemo.cpp - esimerkki säikeistä

	#include <owl/button.h>
	#include <classlib/thread.h>
	
	#include "saieapp.rh" // Def of all resources
	
	
	
	
	
	
	const int SAIKEITA = 20;    // Säikeiden lkm
	const int PAIVITYS = 100000;// Minkä väl.päiv.
	const int KIERROKSIA = 1000000;
	
	
	
	class cLaskuri : public TThread
	// Laskurisäie perit.yleisestä säikeestä
	// ja siihen lisätään omat erikoispiirt.
	{
	  TControl *Text;  //Mihin teksti-ikkunaan
	  int n;           //Sis. laskurin arvo
	  int raja;        //Mihin asti lasketaan
	protected:
	  void count();    //Yhden laskuaskeleen suor
	  //Perit.luokan Run korvataan omalla
	  int Run();
	public:
	  //Rakentaja, joka alustaa mm. sis. muut.
	  cLaskuri(TControl *oLabel,int r) :
	    Text(oLabel), raja(r), n(0) {}
	  ~cLaskuri() { ;}
	};
	
	//{{TDialog = TFormSaieDemo}}
	class TFormSaieDemo : public TDialog {
	// Lomake,jossa laskureita pyöritetään
	    TControl *Labels[SAIKEITA];
	    cLaskuri *saikeet[SAIKEITA];
	  public:
	    TFormSaieDemo(TWindow* parent,
	               TResId resId = IDD_SAIEDEMO,
	               TModule* module = 0);
	    virtual ~TFormSaieDemo();
	
	//{{TFormSaieDemoVIRTUAL_BEGIN}}
	  public:
	    virtual bool Create();
	    virtual TResult EvCommand(uint id,
	           THandle hWndCtl, uint notifyCode);
	    virtual bool CanClose();
	//{{TFormSaieDemoVIRTUAL_END}}
	
	//{{TFormSaieDemoRSP_TBL_BEGIN}}
	  protected:
	    void BNKaynnistaClicked();
	//{{TFormSaieDemoRSP_TBL_END}}
	DECLARE_RESPONSE_TABLE(TFormSaieDemo);
	};    //{{TFormSaieDemo}}
	

saie\saiedemo.cpp - esimerkki säikeistä

	#include <owl/pch.h>
	
	#include "saiedemo.h"
	
	#define ALKU_ID 3000
	
	//-------------------------------------------
	// cLaskuri =================================
	//-------------------------------------------
	
	//-------------------------------------------
	void cLaskuri::count()
	{
	  n++;
	  if ( n % PAIVITYS == 0 ) {
	    char s[30];
	    wsprintf(s,"%d",n);
	    Text->SetWindowText(s);
	  }
	}
	
	//-------------------------------------------
	int cLaskuri::Run()
	// Tämä suorittaa varsinaisen säikeen
	// toimenpiteet.  Kun tämä metodi loppuu,
	// pysähtyy säie. 
	{
	  const char *mes="";
	  while ( n < raja ) {
	    if ( ShouldTerminate() ) {
	      mes = "T";  break;
	    }
	    count();
	  }
	  char s[30];
	  wsprintf(s,"%d%s",n,mes);
	  Text->SetWindowText(s);
	  return 0;
	}
	
	//-------------------------------------------
	// TFormSaieDemo ============================
	//-------------------------------------------
	
	//-------------------------------------------
	DEFINE_RESPONSE_TABLE1(TFormSaieDemo,TDialog)
	//{{TFormSaieDemoRSP_TBL_BEGIN}}
	  EV_BN_CLICKED(IDKAYNNISTA,
	                BNKaynnistaClicked),
	//{{TFormSaieDemoRSP_TBL_END}}
	END_RESPONSE_TABLE;
	
	//{{TFormSaieDemo Implementation}}
	
	//-------------------------------------------
	TFormSaieDemo::TFormSaieDemo(TWindow* parent,
	 TResId resId, TModule* module)
	  :  Tdialog(parent, resId, module)
	{
	}
	
	
	//-------------------------------------------
	TFormSaieDemo::~TFormSaieDemo()
	{
	  Destroy();
	}
	
	//-------------------------------------------
	static bool Clear(cLaskuri * &saie)
	// Tämä funktio tarkistaa onko säie jo
	// siivottu, eli se on tuhottu.
	// Mikäli säie ei ole tuhottu, mutta se
	// on valmis, tuhotaan säie.
	{
	  if ( saie == NULL ) return true;
	  if ( saie->GetStatus() !=
	         TThread::Finished ) return false;
	  delete saie;
	  saie = NULL;
	  return true;
	}
	
	//-------------------------------------------
	void TFormSaieDemo::BNKaynnistaClicked()
	{
	  for (int i=0; i<SAIKEITA; i++) {
	    if ( !Clear(saikeet[i]) ) continue;
	    saikeet[i] = new cLaskuri(Labels[i],
	                                 KIERROKSIA);
	    saikeet[i]->Start();
	  }
	  saikeet[0]->SetPriority(
	    THREAD_PRIORITY_ABOVE_NORMAL);
	}
	
	
	
	
	//-------------------------------------------
	TResult TFormSaieDemo::EvCommand(uint id,
	            THandle hWndCtl, uint notifyCode)
	// Jos laskuria klik., "tapetaan vast.säie"
	{
	  TResult result=TDialog::EvCommand(id,
	                         hWndCtl,notifyCode);
	  int i = id-ALKU_ID;
	  if ( 0 <= i && i < SAIKEITA )
	    if ( !Clear(saikeet[i]) )
	      saikeet[i]->Terminate();
	  return result;
	}
	
	//-------------------------------------------
	bool TFormSaieDemo::Create()
	// Luodaan laskurit alekkain näytölle
	{
	  bool result;
	
	  int y = 10, dy = 20;
	  for (int i=0; i<SAIKEITA; i++) {
	    saikeet[i] = NULL;
	    Labels[i] = new Tbutton(this,ALKU_ID+i,
	                         "Terve",10,y,70,dy);
	    y += dy;
	  }
	
	  result = Tdialog::Create();
	
	  TRect rc = this->GetWindowRect();
	  rc.top = 0; rc.bottom = rc.top + y + 50;
	  this->MoveWindow(rc,TRUE);
	
	  return result;
	}
	
	bool TFormSaieDemo::CanClose()
	{
	  bool result = TDialog::CanClose();
	
	  for (int i=0; i<SAIKEITA; i++) {
	    if ( Clear(saikeet[i]) ) continue;
	    result = false;
	    saikeet[i]->Terminate();
	  }
	
	  return result;
	}
	

saie\saiedemo.pas - esimerkki säikeistä

	unit saiedemo;
	
	interface
	
	uses
	  Windows, Messages, SysUtils, Classes,
	  Graphics, Controls, Forms, Dialogs,
	  StdCtrls;
	
	
	const SAIKEITA = 20;    // Säikeiden lkm
	      PAIVITYS = 100000;// Minkä välein päiv.
	      KIERROKSIA = 1000000;
	
	type
	  //-----------------------------------------
	  cLaskuri = class(TThread)
	  // Laskurisäie perit.yleisestä säikeestä
	  // ja siihen lisätään omat erikoispiirt.
	  private
	    Text : TLabel;   //Mihin teksti-ikkunaan
	    n:integer;       //Sis. laskurin arvo
	    raja:integer;    //Mihin asti lasketaan
	  protected
	    procedure count; //Yhden laskuaskeleen su
	    //Perit.luokan Execute korvataan omalla
	    procedure Execute; override;   
	  public
	    //Rakentaja, joka alustaa mm. sis. muut.
	    constructor Create(oLabel:TLabel;
	                       r:integer);
	  end;
	
	
	  //-----------------------------------------
	  TFormSaieDemo = class(TForm)
	  // Lomake,jossa laskureita pyöritetään
	    ButtonKaynnista: TButton;
	    procedure ButtonKaynnistaClick(
	      Sender: TObject);
	    procedure ThreadDone(Sender:TObject);
	    procedure FormCreate(Sender: TObject);
	    procedure LabelsClick(Sender: TObject);
	  private
	    { Private declarations }
	    Labels: Array [0..SAIKEITA-1] of TLabel;
	    saikeet:Array[0..SAIKEITA-1] of cLaskuri;
	 public
	    { Public declarations }
	  end;
	
	
	
	
	
	
	
	
	
	
	
	//-------------------------------------------
	// Globaalit muuttujat
	//-------------------------------------------
	var
	  FormSaieDemo: TFormSaieDemo;
	
	implementation
	
	//-------------------------------------------
	// cLaskuri =================================
	//-------------------------------------------
	
	//-------------------------------------------
	procedure cLaskuri.count;
	begin
	  inc(n);
	  if ( n mod PAIVITYS = 0 ) then
	    Text.Caption := IntToStr(n);
	end;
	
	
	
	
	//-------------------------------------------
	procedure cLaskuri.Execute;
	// Tämä suorittaa varsinaisen säikeen
	// toimenpiteet.  Kun tämä metodi loppuu,
	// pysähtyy säie.  Säie häviää autom.
	// jos FreeOnTerminate := True
	var mes:String;
	begin
	  mes := '';
	  while ( n < raja ) do begin
	    if terminated then begin
	      mes := 'T'; Break;
	    end;
	    count;
	  end;
	  Text.Caption := IntToStr(n)+mes;
	end;
	
	//-------------------------------------------
	constructor cLaskuri.Create(oLabel:TLabel;
	                                  r:integer);
	begin
	  inherited Create(False);
	  Text := oLabel;
	  raja := r;
	  n := 0;
	  FreeOnTerminate := True;
	end;
	
	{$R *.DFM}
	
	//-------------------------------------------
	// TformSaieDemo ============================
	//-------------------------------------------
	
	
	
	
	
	
	
	
	
	
	
	
	
	//-------------------------------------------
	procedure TFormSaieDemo.ThreadDone(
	                             Sender:TObject);
	// Tämä tapahtuma, kun jokin säie valmistuu.
	var i:integer;
	begin
	  for i:=0 to SAIKEITA-1 do // Etsitään säie
	    if ( Sender = saikeet[i] ) then
	      saikeet[i] := NIL;
	end;
	
	
	
	
	
	//-------------------------------------------
	procedure TFormSaieDemo.ButtonKaynnistaClick(
	                            Sender: TObject);
	var i:integer;
	begin
	  // Luodaan uudet säikeet niiden tilalle
	  // joita ei ole
	  for i:=0 to SAIKEITA-1 do
	    if (  saikeet[i] = NIL ) then begin
	      saikeet[i] :=
	       cLaskuri.Create(Labels[i],KIERROKSIA);
	      saikeet[i].OnTerminate := ThreadDone;
	    end;
	  saikeet[0].Priority  := tpHigher;
	end;
	
	//-------------------------------------------
	procedure TFormSaieDemo.LabelsClick(
	                             Sender:TObject);
	// Jos laskuria klik., "tapetaan vast.säie"
	var i:integer;
	begin
	  i := (Sender as  TLabel).Tag;
	  if ( saikeet[i] <> NIL ) then
	    saikeet[i].Terminate;
	end;
	
	
	
	//-------------------------------------------
	procedure TFormSaieDemo.FormCreate(
	                            Sender: TObject);
	// Luodaan laskurit alekkain näytölle
	var i,y,dy:integer;
	begin
	  y := 10; dy := 20;
	  for i:=0 to SAIKEITA-1 do begin
	    saikeet[i] := NIL;
	    Labels[i] := TLabel.Create(Self);
	    Labels[i].AutoSize := False;
	    Labels[i].top := y;
	    Labels[i].left := 10;
	    Labels[i].Width := 70;
	    Labels[i].Caption := 'Terve';
	    Labels[i].Parent := Self;
	    Labels[i].Tag := i;
	    Labels[i].OnClick := LabelsClick;
	    y := y + dy;
	  end;
	  Top := 0; Height := y + 50;
	end;
	
	end.

Tehtävä 2.18 TLabel => TButton

Muuta saiedemo.pas- esimerkissä laskurikentät nappuloiksi.


Prev Next Up Title Contents Index