17 Ağustos 2014 Pazar

Delphi ile Kolay Thread Kullanımı


Delphi de Thread konusu yıllardır insanları korkutmuştur. Bugün çok basit bir örnek ile "Thread" i biraz inceleme fırsatı bulacağız.

Öncelikle Thread kullanırken hakkında bilmemiz gereken bir şey var. Thread Create edildiğinde eğer özellikle belirtilmedi ise hemen çalışmaya başlar. TThread sınıfı içerisinde Execute metodu vardır ve thread'in başlaması demek aslında Execute metodunun çalışması demektir. Execute metodunu Override ederek thread'in bizim istediğimiz şeyleri yapmasını sağlıyıcaz. Az önce söylediğim gibi özellikle belirtilmedi ise otomatik başlıyor. Peki bunu özellikle nasıl belirteceğiz.? Hemen cevap verelim. Şöyle ki, Create Metodu içerisinde "inherited Create(False);" gibi bir tanımlama yapacağız ki otomatik olarak başlamasın. Peki otomatik başlamayacaksa biz hazır olduğumuzda nasıl başlatacağız? Kilit cevap "Resume" metodunda yatıyor. Hazır olduğumuzda Thread'imizin başlaması için ( Execute Metodunun Başlaması ) Resume Metodunu kullanıyoruz.




Projemizin kodları aşağıdaki gibidir.

const
  WM_MY_MESSAGE = WM_USER + 1;

type
TForm1 = class(TForm)
    memoX: TMemo;
    memoY: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure Write(var Msg: TMessage); message WM_MY_MESSAGE;
  end;


  TMyThreadClass = class(TThread)
  Private
    FValue: Integer;
    FMainFormHandle: HWND;
    FComponentHandle: HWND;
    FDelay: Integer; // MilliSecond
  public
    procedure Execute; OverRide;

    constructor Create(MainFormHandle: HWND; Delay: Integer);
  end;



constructor TMyThreadClass.Create(MainFormHandle: HWND; Delay: Integer);
begin
  inherited Create(False); // Otomatik Olarak Başlama, Resume; Metodunu Bekle
  FreeOnTerminate := True; // Terminate Edildiğinde Class Free Olsun
  FMainFormHandle := MainFormHandle;
  FValue := 0;
  FDelay := Delay;
  Resume;
end;

procedure TMyThreadClass.Execute;
begin
  inherited;
  While (not Terminated) and  (FValue > 0) do
  begin
    SendMessage(FMainFormHandle, WM_MY_MESSAGE, FComponentHandle, FValue);
    Dec(FValue);
    Sleep(FDelay);
  end;
  Terminate;
end;

{ TForm1 }

procedure TForm1.Write(var Msg: TMessage);
begin
  if Msg.WParam = memoX.Handle then
    memoX.Lines.Add(IntToStr(Msg.LParam))
  else if Msg.WParam = memoY.Handle then
    memoY.Lines.Add(IntToStr(Msg.LParam));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Thread1, Thread2: TMyThreadClass;
begin
  Thread1 := TMyThreadClass.Create(Self.Handle, 1000);
  Thread1.FValue := 10;
  Thread1.FComponentHandle := memoX.Handle;

  Thread2 := TMyThreadClass.Create(Self.Handle, 500);
  Thread2.FValue := 20;
  Thread2.FComponentHandle := memoY.Handle;
end;


Tanımlamalardan anlayacağınız gibi formumuz üzerinde 2 adet memo ve 1 adet buton nesnesi var.

Thread class'ımızı tanımlarken TThread sınıfından türetiyoruz. Böylece thread'i class içerisinde kullanmamıza olanak doğmuş oluyor. Delphi ile Thread kullanırken TThread sınıfının VCL ile uyumlu olmadığını bilmekte fayda var. Bu yüzden bir Thread class ı içerisinden başka class lardaki veya MainForm üzerindeki VCL'lere erişmemeye gayret gösteriyoruz. Ben bunun için SendMessage metodu ile Window Messages kullanarak MainForm'a mesaj gönderdim.

Execute metodu Thread in başladığında işleyeceği kodları oluşturmalıdır. Burada genelde bir döngü kurulur ve bu döngü sürekli çalışır. Belli sürede çalışması için ise Sleep metodu kullanılır.

Butona basıldığında aynı class'tan 2 tane create ettim. FValue özelliğini ve Delay parametresini farklı verdim.
Thread1 isimli class 1000 Milisaniye de FValue değerini MainForm'a mesaj gönderecek. Thread2 ise 500 Milisaniye de bir FValue değerini mesaj olarak gönderecek.

Biz ise belirlenen gecikme süresinde memo nesnelerine bu değerleri ekliyoruz.

Korkulacak bir şey yok. Thread'lerin üzerine gidin ve kazanmaya inanın. Başaracaksınız.












2 yorum:

  1. Bu yorum bir blog yöneticisi tarafından silindi.

    YanıtlaSil
  2. Teşekkürler. Aslında video ile örneklendirerek anlatsanız çok daha iyi olur kanısındayım. Anlatım içim teşekkür ederim

    YanıtlaSil