Thread.terminate yapınca access violation hatası!!!

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Thread.terminate yapınca access violation hatası!!!

Mesaj gönderen huseyinkucuk »

("thread.terminate yapınca access violation hatası" başlığıyla ilgili soru en alttadır... Lütfen aşağıya bakın... Şimdiden teşekkür ederim...)

Arkadaşlar, merhaba...
Aynı kaynakları kullanan threadların birbirlerinin sırasını beklemek için sanırım 'critical section' kullanmam gerekiyomuş... Forumda aradım, bişey bulamadım... Google'la da aradım ama ordan da pek bişey bulamadım... 'Critical Section' nedir? Nasıl kullanılır? Bir örnekle kısaca anlatabilecek var mı acaba? Yardımlarınızı bekliyorum... Şimdiden teşekkür ederim, kolay gelsin...
En son huseyinkucuk tarafından 30 May 2006 07:57 tarihinde düzenlendi, toplamda 5 kere düzenlendi.
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Delphi Help dosyasında Critical Section bölümünde örnekli bir açıklama mevcut.

Aynı zamanda multi-read exclusive-write synchronizer başlığına da göz atmanı öneririm.

Critical section ve mutex'lerin amacı senin de tahmin edebileceğin gibi, bir thread, diğer thread'ler ile veri paylaştığı, okuduğu-yazdığı alana, yazmak isterse, yazma işleminin aynı anda sadece 1 thread ile sınırlı olmasını sağlamaktır.

Mutex'in critical section'dan farkı şudur. Mutex kullandığında bütün thread'ler aynı anda paylaşımlı bölgeyi okuyabilir ancak sadece bir tanesi yazabilir.

Critical section'da ise bir thread'in işi bitene kadar diğer threadler durdurulur.

Sıkça yazma işlemi gerekmeyen yerlerde mutex kullanmak genel performansı arttıracaktır. Mutex kullanılması tavsiye edilir.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

Teşekkür ederim... Sanırım çözdüm olayı... CriticalSectionNesnesi.acquire işlemler, işlemler... CriticalSectionNesnesi.release; böyle bişeyler... Çok teşekkürler... Kolay gelsin...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

huseyinkucuk yazdı:Teşekkür ederim... Sanırım çözdüm olayı... CriticalSectionNesnesi.acquire işlemler, işlemler... CriticalSectionNesnesi.release; böyle bişeyler... Çok teşekkürler... Kolay gelsin...
Sayın huseyinkucuk,

Bu kanal işleri zamanında bana kafayı yedirmek üzereydi. Bu işleme kanal senkronizasyonu deniyor. Öncelikle eğer bir takım işlemleri kanallar ile gerçekleştirecekseniz kanalların kodlarını çok iyi planlamanız gerekiyor.

Aksi takdirde bir takım sorunlar olduğunda, kanalların birbiriyle eş zamanlı olarak çalışmasından dolayı hataları gidermeniz çok zor olabilir.

Benim durumumda, kanallaırn hepsi sonunda suspended konumuna geçiyordu ve bir türlü nedenini bulamıyordum. Bunun üzerine adım adım kodlara OutputDebugString fonksiyonuyla mesajlar çıkarttırıp, uygulamayı memproof ile açarak sorunu çözebilmiştim. Hala bu uygulama ara sıra kendi kendini kapatıyor. :oops:

Başarılar
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

ya hocam sorma ya, kafayı yicem... Herşeylerini planlı programlı yaptım bu threadların, herşeylerini lokal değişken yaptım birbirlerinin işlerine karışmasınlar diye. Arada bi yine hata veriyo, yine hata veriyo...

Formda düğmeye basınca rasgele biyerlerden küçük küçük tanklar çıkıp rasgele biyerlere doğru gidiyolar... Başta herşey çok güzeldi, hepsi kendi yolunda gidiyo ama birbirlerini farketmiyolardı, yani birbirlerinin içinden geçiyolardı. Ben dedim yaw bunlar çarpışınca yok olsun (ilk önce geri dönsünler diye düşünmüştüm ama sonra yokolsun dedim, demez olaydım, geri dönselerdi hiç bi problemle uğraşıyo olmıcaktım şimdi :) free edince çıkıyo sanırım problemler) Çarpışıyolar falan, bi kaç (bazen daha çok) çarpışmadan sonra zırt pırt access violation hatası verip duruyo... Ama program normal çalışmaya devam ediyo, sadece hatayı verip duruyo. Aslında try except ile falan hatanın görünmemesini sağlarım ama kendime yediremem bunu :) Bana yardım edebilecek yok mu? Critical Section'un da nasıl kullanıldığını anlamadım zaten, hiçbiyerde yazmıyo (bi şekilde kullanayım dedim ama işe yaramadı, ya yanlış kullandım ya da işe yaramıyo) Arkadaşlar, rapide yükledim projeyi, incelemek isteyen varsa buyursun, yardım ederseniz müteşekkir olurum. Herkese kolay gelsin...
http://rapidshare.de/files/21371916/Thr ... 2.rar.html
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Akin_Delphi
Üye
Mesajlar: 163
Kayıt: 06 Nis 2006 12:22

Mesaj gönderen Akin_Delphi »

huseyinkucuk yazdı:ya hocam sorma ya, kafayı yicem... Herşeylerini planlı programlı yaptım bu threadların, herşeylerini lokal değişken yaptım birbirlerinin işlerine karışmasınlar diye. Arada bi yine hata veriyo, yine hata veriyo...
Valla sizin açınızdan üzüldüm. :( Belki yanlış bir düşünce ancak şunu söylemek isterim: Muhtemelen oluşturduğunuz TTank bileşenlerini ana formda (yani dolayısıyla ana kanalda) kullanmanız bir takım sorunlar oluşturuyor olabilir.
huseyinkucuk yazdı:Critical Section'un da nasıl kullanıldığını anlamadım zaten, hiçbiyerde yazmıyo (bi şekilde kullanayım dedim ama işe yaramadı, ya yanlış kullandım ya da işe yaramıyo) Arkadaşlar, rapide yükledim projeyi, incelemek isteyen varsa buyursun, yardım ederseniz müteşekkir olurum. Herkese kolay gelsin...
Bu konuda size herhangi birinin yardımcı olabileceğini sanmıyorum. Çünkü uygulamanın mantığını ancak siz bilebilirsiniz. Kanal senkronizasyonunun mantığı belirli verilere kanalların sırayla ulaşmasını sağlamak. Kiritik Bölümlerin standart bir kullanımı maalesef ki bulunmuyor. Dolayısıyla, size kimse somut bir örnek veremez. Bence Memproof ya da Delphi IDE'nin Debug panelinden yararlanıp, kanal kodu (ve ana formun kodları) içerisinde erişim ihlallerinin vs.'nin çıktığından şüphelendiğiniz yerlerin (yani kod satırlarının) hemen öncesine Outputdebugstring('xx'inci satıra geldi') vs. gibi mesajlar çıkarttırıp, erişim ihlallerinin hangi satırlar sonrasında meydana geldiğini tespit etmeye çalışmalısınız.

Başka bir fikir de, Jedi bileşen paketinin JVManagedThread bileşenlerini kullanmak. En azından bu hazır bileşenler sayesinde kanalları ana form içerisinde oluşturabilir ve tanklarınızı yönetebilirsiniz. Ancak belki benim kişisel beceriksizliğimden kaynaklanıyor olabilir, tam olarak bilmiyorum. Fakat ben kullandığımda bu JVManagedThread bileşenleri korkunç bellek sızıntısına neden oluyordu. :oops:

Kanalları önce JVManagedThread bileşenleri ile kullandım ve daha sonra bunu normal unit şeklindeki kanallara taşıdım. Şu anda çok fazla sorun yok. Ancak ara sıra kendi kendine uygulama kapanıyor. Bu profesyonel bir uygulama olmadığından dolayı çok fazla da uğraşmıyorum işin açıkçası. Çünkü dediğim gibi kanal sorunu gerçekten insana kafayı sıyırttırıyor. :D

Saygılar ve Başarılar.
Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

huseyinkucuk yazdı: Critical Section'un da nasıl kullanıldığını anlamadım zaten, hiçbiyerde yazmıyo (bi şekilde kullanayım dedim ama işe yaramadı, ya yanlış kullandım ya da işe yaramıyo)
http://www.marcocantu.com/code/md5/THSY ... RISECT.PAS

Kod: Tümünü seç

unit TCriSect;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, SyncObjs;

type
  TListThread = class (TThread)
  private
    Str: String;
  protected
    procedure AddToList;
    procedure Execute; override;
  public
    LBox: TListBox;
  end;

  TForm5 = class(TForm)
    BtnStart: TButton;
    ListBox1: TListBox;
    ListBox2: TListBox;
    procedure BtnStartClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Th1, Th2: TListThread;
  public
    { Public declarations }
  end;

var
  Form5: TForm5;
  Letters: string = 'AAAAAAAAAAAAAAAAAAAA';
  Critical1: TCriticalSection;

implementation

{$R *.DFM}

procedure TListThread.AddToList;
begin
  if Assigned (LBox) then
    LBox.Items.Add (Str);
end;

procedure TListThread.Execute;
var
  I, J, K: Integer;
begin
  for I := 0 to 50 do
  begin
    Critical1.Enter;
    for J := 1 to 20 do
      for K := 1 to 2601 do // useless repetition...
        if Letters [J] < 'Z' then
          Letters [J] := Succ (Letters [J])
        else
          Letters [J] := 'A';
    Str := Letters;
    Critical1.Leave;
    Synchronize (AddToList);
  end;
end;

procedure TForm5.BtnStartClick(Sender: TObject);
begin
  ListBox1.Clear;
  ListBox2.Clear;
  Th1 := TListThread.Create (True);
  Th2 := TListThread.Create (True);
  Th1.FreeOnTerminate := True;
  Th2.FreeOnTerminate := True;
  Th1.LBox := Listbox1;
  Th2.LBox := Listbox2;
  Th1.Resume;
  Th2.Resume;
end;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Critical1 := TCriticalSection.Create;
end;

procedure TForm5.FormDestroy(Sender: TObject);
begin
  Critical1.Free;
end;

end
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

Arkadaşlar, teşekkür ederim... Eve gidince denicem bunu... Marco Cantu'nun kitabı da var ama orda da thread'ler ile ilgili pek fazla bilgi bulamadım... Demek ki sitesinde varmış... Teşekkür ederim, hepinize kolay gelsin... Yeni sorularımla başınızı ağrıtabilirim, ilgilendiğiniz için teşekkürler...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Mesaj gönderen Opt2000 »

Selam,

Senin sorunun Critical Section'la ilgili değil sanırım. Kodda bir iki değişiklik yaptım ve RapidShare tekrar attım. Uzun bir süre beklememe ve bir sürü çarpışma olmasına rağmen hata vermedi. Linki aşağıda.

http://rapidshare.de/files/21416677/Tank.rar.html

Anladığım kadarıyla asıl sorun şurada. Tank listesini her seferinde dinamik olarak çıkarıyorsun, ama bu liste sana her zaman gerçek listeyi vermiyor. Kimi zaman listedeki tanklardan birisi terminated ve dolayısıyla silinmiş olabiliyor. Pek doğru olmamasına rağmen farklı bir şekilde bir çözüm ürettim. Ana forma bir tane TList yerleştirdim ve eklenen bütün tankları bu listeye attım. Daha sonra da Thread içinde tank listesini dinamik almadım, onun yerinde ana formdaki listeyi kullandım. Ana liste daima son eleman listesini tuttuğu için problem yaratmayacaktır (Eğer bu sistemi birebir kullanacaksan, burada range kontrolü yaptırman iyi olur) Eğer Critical Section kullanılacaksa, bu listeye erişirken kullanılmalı. Ama sen bu listeye erişen kodları syncronize içine altığın için, burada da problem olacağını sanmıyorum. Zaten kodun tamamı sync içinde olduğu için ve aynı zamanda kodlarında bazı optimizasyonlar eksik olduğu için tanklar hareket ederken çok fazla titreme yapıyor.

Ana listenin sürekli güncel olması gerektiği için, herhangi bir thread silineceği zaman, aynı zamanda listeden de silinmeli. Bu yüzden FreeOnTerminate şeklinde çalışması sorun yaratır. Bunu da kendi tanımladığım bir mesajı ana forma göndererek hallettim (WM_ThreadEnd).

Program kapanırken bütün threadlerin sona erdirilmesini de bekletiyor. Bu yüzden program kapanırken kısa bir süre bekliyor.

Ayrıca Tank sınıfında da bellek kaybı oluşuyor. Eğer programın sendeki sürümünü çalıştırırken Task Manager'i açacak olursan, kullanılan bellek miktarının sürekli arttığını ve nesneler yok edilmesine rağmen alınan belleğin geri verilmediğini göreceksin. Ben buna da bir şeyler yaptım, asıl sorun class'ın constructor'ında create ettiğin Image nesnelerini, destory ederken silmiyor olman. Ayrıca constructor'ınla ilgili de warning veriyor. Ben senin yerinde olsam, bu warningi engelleyecek şekilde kodu değiştirirdim.

Son olarak ben senin yerinde olsam kesinlikle böyle hazırlamazdım. Tank resimlerin standart. Bu yüzden bir class hazırla, bu class tank yeri ve yönünü tutsun. Bu yöne göre de bir image listesinden hangi resmi kullanacağını bilsin. Yani bütün programda toplam 8 tane resim olacak. Class gerektiği zaman canvasa bu resimleri çizdirsin. Böylece çok daha az bellek kullanmış olursun. Çünkü 20 tane tank yarattığın zaman bellek kullanımı ciddi oranda yükseliyor.

Ayrıca threadlerle ilgili can sıkıcı bir durum daha var. Her ne kadar MS yapsa bile, dokumanlarda 20'den fazla thread kullanımını pek tavsiye etmiyor. Bunun iki sebebi olabilir, bir performansın fazla düşmesi, iki her threadin aksini belirtmediğin sürece en az 1 MB yer tutması. Henüz sadece başlangıç aşamasında bu kadar çok thread kullanman, projenin devamı için sakat bir durum.

Eğer oyun yazmayı düşünüyorsan, işin bu kısmını threadle yapmamalısın zaten. Çünkü thread, aynı anda iki farklı işlem için kullanılır. Oysa senin yapmak istediğinde, o an ekranda x tane tank göstermek. Ayrıca oyundaki animasyonlar time based olacağı için, zaten threadleri durdurman gerekecek. Bu yüzden aslında benim yukarıda yazdığım gibi class hazırlaman ve bunları adam gibi bir listede tutman daha iyi olacaktır. Bu listede yapacağın buble sort algoritması ile de çarpışmaları tespit edip, listede eleme yapmalı ve sonra da listeyi ekrana basmalısın. Time-based bir sistemde thread kullanmanın bir anlamı yok. Oyunlarda da zaten bu kısımlar thread ile yapılmıyor. Thread ile daha çok yapay zeka kısmı yapılıyor. Normalde bütün animasyonlar yapılır (yani poligonların yeni pozisyonları bir şekilde belirlenir - bir şekilde dememin özel bir sebebi var, çünkü bunun 3 farklı yöntemi var) sonra da poligon bufferının ekrana basılacağı komutu verilir, poligonlar buffera yazılır (Buffer burada ekran kartı da olabilir, sistem belleği de, tamamen kullanılan enginein yapısına bağlı). Son olarak bütün poligonların buffera yazıldığı komutu gönderilir. Engine bu komutu aldıktan sonra gösterilecek olan resmi oluşturur ve bunu ekrana basar. Dikkat edersen bu sistemde thread falan yok. Dümdüz bir fonksiyon var aslında. Hatta C++'daki template kütüphanes (STL) bu işlemler için yavaş kaldığından dolayı oyun programcılığında STL kullanılmaz, onun yerine hand optimized listeler kullanılır.

Ayrıca zamanlama için standart timerı da kullanamazsın, high precision bir timera ihtiyacın var. Bunu da Jedi kütüphanesinde bulabilirsin (Yanlış hatırlıyor olabilirim, ama en kötü nette arattırırsın). Gerçi GDI fonksiyonları ile oyunu pek fazla ilerletemezsin ama başlangıçta OpenGL ya da DirectX kullanmaktan daha kolay olacağı kesin.

Kolay gelsin,
Bahadır Alkaç
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

hocam, teşekkür ederim, harikasın. Sanırım gerçekten de çözmüşsün problemi. Kodları ve yazını tam okuyamadım, misafirim var. Daha sonra okucam. Tebrik ediyorum ve teşekkür ediyorum. Kolay gelsin... (Bundan sonra da yardımlarını bekliyorum, saol)
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

Bahadır hocam, teşekkür ederim, benim için o kadar uğraşmışsın, emek vermişsin... Umarım benim problemimi çözmek senin ilerlemene de yardımcı olmuştur... Hocam, aslında amacım oyun ahazırlamak falan değil (bazen aklımdan geçse de bu işi çok da iyi yapamayacağımı biliyorum (en azından şimdilik)), ben thread'leri yeni yeni öğreniyorum, bi iki şey yaptım işte; ekranın farklı yerlerinde 0dan 100 e kadar sayan sayılar falan (kitaptaki örnekler gibi bişey yani), Sonra kendi kendime dedim, yaw dedim, ben böyle hareket eden, birbirini farkeden nesneler yapamaz mıyım? dedim. Daha önceden yön tuşlarıyla hızlandırıp yavaşlattığım, formun kenarlarına çarpan bi tank yapmıştım (normal döngüyle), sonra threadla bu tankların küçüklerinden istediğim kadar yapayım da bakalım birbirlerini görebilecekler mi (yani çarpışabilecekler mi? gibi) diye yaptım. Anlayacağın tek amacım şimdilik kendi sınırlarımı görebilmekti. Yazdıklarına göre çok da ilerleyememişim :) Ama umarım hepsini hallederim... Doğru diyosun, oyun yazma açısından çok da güzel bir yol seçmedim, söylediğim gibi, amacım sadece thread'leri öğrenmekti... Bu başlığı açmamdaki amacım da yaptığım uygulamanın niye hata verdiğini öğrenmekti. Hatanın sebebini anladım sanırım... Hocam çok teşekkür ederim... Kendine iyi bak... Kolay gelsin...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

Arkadaşlar, başka bir başlıkla yazmam gerekebilirdi ama önceden yazdığımla az buçuk alakalı diye buraya yazma gereği duydum...
Aşağıdaki kodu yazdım. Kendi yaptığım thread sınıfı yine kendi yaptığım başka bir sınıfı kullanıyor... Thread'ı yaratıyorum, tlist içinde tutuyorum yaratılanları, yokederken de tthreadtank(list.items).terminate; gibi yokediyorum... Access violation hatası veriyor, sebebi ne olabilir acaba? Kodu aşağıda veriyorum...

Kod: Tümünü seç

unit UAnaUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ImgList,extctrls, StdCtrls,
  UTank,UThreadTank;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    Image4: TImage;
    Image5: TImage;
    Image6: TImage;
    Image7: TImage;
    Image8: TImage;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  TankListesi:TList;
  Sayac:integer;   

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  TankListesi:=TList.Create;
  Sayac:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Tankim:TThreadTank;
begin
    Tankim:=TThreadTank.create(application.MainForm,100,100,yKuzey,1,50,50,100,100,100);
    Tankim.Priority:=tpLowest;
    TankListesi.Add(Tankim);
    form1.Caption:=inttostr(tanklistesi.Count);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if tanklistesi.Count<=0 then exit;
  TThreadTank(TankListesi.Items[tanklistesi.Count-1]).terminate;
  TankListesi.Delete(TankListesi.Count-1);
end;

end.

Kod: Tümünü seç

unit UTank;

interface
Uses StdCtrls,extctrls,controls;
Type TYonler=(yKuzey,yGuney,yDogu,yBati);

//////////////////////////////////////////
Type TTank=Class(TImage)
private
  FYon:TYonler;
  FHiz:Integer;
  FXKonumu:Integer;
  FYKonumu:integer;
  FGenisligi:integer;
  FBoyu:integer;
  FNumarasi:integer;
  FHasar:integer;
  FHasaraKarsiDayanmaGucu:integer;
  FEziciGucu:integer;
  FSilahGucu:integer;
  FOwner:TWinControl;
  FKursunSayisi:integer;
  FEkrandakiKursunSayisi:integer;
  FYokettigiTankSayisi:integer;
  Palet:boolean;
    procedure SetBoyu(const Value: integer);
    procedure SetEziciGucu(const Value: integer);
    procedure SetGenisligi(const Value: integer);
    procedure SetHasar(const Value: integer);
    procedure SetHasaraKarsiDayanmaGucu(const Value: integer);
    procedure SetHiz(const Value: integer);
    procedure SetNumarasi(const Value: integer);
    procedure SetSilahGucu(const Value: integer);
    procedure SetXKonumu(const Value: integer);
    procedure SetYKonumu(const Value: integer);
    procedure SetYon(const Value: TYonler);
    procedure SetEkrandakiKursunSayisi(const Value: integer);
    procedure SetKursunSayisi(const Value: integer);
    procedure YoneGoreResimTayinEt;
protected
public
  property Yon:TYonler read FYon Write SetYon;
  property Hiz:integer read FHiz write SetHiz;
  property XKonumu:integer read FXKonumu write SetXKonumu;
  property YKonumu:integer read FYKonumu write SetYKonumu;
  property Genisligi:integer read FGenisligi write SetGenisligi;
  property Boyu:integer read FBoyu write SetBoyu;
  property Numarasi:integer read FNumarasi write SetNumarasi;
  property Hasar:integer read FHasar write SetHasar;
  Property HasaraKarsidayanmaGucu:integer read FHasaraKarsiDayanmaGucu write SetHasaraKarsiDayanmaGucu;
  Property EziciGucu:integer read FEziciGucu write SetEziciGucu;
  property SilahGucu:integer read FSilahGucu write SetSilahGucu;
  property Owner:TWinControl read FOwner;
  property KursunSayisi:integer read FKursunSayisi write SetKursunSayisi;
  property EkrandakiKursunSayisi:integer read FEkrandakiKursunSayisi write SetEkrandakiKursunSayisi;
  constructor create(AOwner:TWinControl;X,Y:Integer;AYon:TYonler;AHiz:integer;ABoy,AGenislik:integer;AEziciGucu:integer;AHasaraKarsiDayanmaGucu:integer;ASilahGucu:integer);
  procedure HareketEttir;
  destructor destroy;override;
end;
////////////////////////////////////////////


implementation
uses UAnaUnit;
{ TTank }



constructor TTank.create(AOwner: TWinControl; X, Y: Integer; AYon: TYonler;
  AHiz, ABoy, AGenislik, AEziciGucu, AHasaraKarsiDayanmaGucu,
  ASilahGucu: integer);
begin
  inherited create(AOwner);
  Parent:=AOwner;
  Stretch:=true;
  Transparent:=true;
  FOwner:=AOwner;
  FXKonumu:=X;Left:=X; //şimdilik çömezim, böyle yaptım...
  FYKonumu:=Y;Top:=Y;  //şimdilik çömezim, böyle yaptım...
  FYon:=AYon;
  FHiz:=AHiz;
  FBoyu:=ABoy; Height:=ABoy; //şimdilik çömezim, böyle yaptım...
  FGenisligi:=AGenislik; Width:=AGenislik; //şimdilik çömezim, böyle yaptım...
  FEziciGucu:=AEziciGucu;
  FHasaraKarsiDayanmaGucu:=AHasaraKarsiDayanmaGucu;
  FSilahGucu:=ASilahGucu;
  Palet:=true;
  YoneGoreResimTayinEt;
end;



destructor TTank.destroy;
begin
  inherited;
end;

procedure TTank.HareketEttir;
begin
  case FYon of
    yKuzey: begin
              YKonumu:=FYKonumu-FHiz;
              if palet then
                picture:=form1.Image1.Picture
              else
                picture:=form1.Image2.Picture;
              if FYKonumu<=0 then
                Yon:=yGuney;
              if FYKonumu-FHiz<0 then
                FYKonumu:=0;
            end;
    yGuney: begin
              YKonumu:=FYKonumu+FHiz;
              if palet then
                picture:=form1.Image3.Picture
              else
                picture:=form1.Image4.Picture;
              if FYKonumu+FBoyu>=FOwner.ClientHeight then
                Yon:=yKuzey;
              if FYKonumu+FBoyu+FHiz>FOwner.ClientHeight then
                FYKonumu:=FOwner.ClientHeight-FBoyu;
            end;
    yDogu:  begin
              XKonumu:=XKonumu+Hiz;
              if palet then
                picture:=form1.Image5.Picture
              else
                picture:=form1.Image6.Picture;
              if FXKonumu+FGenisligi>=FOwner.ClientWidth then
                Yon:=yBati;
              if FXKonumu+FGenisligi+FHiz>FOwner.ClientWidth then
                FXKonumu:=FOwner.ClientWidth-FGenisligi;
            end;
    yBati:  begin
              XKonumu:=XKonumu-Hiz;
              if palet then
                picture:=form1.Image7.Picture
              else
                picture:=form1.Image8.Picture;
              if FXKonumu<0 then
                Yon:=yDogu;
              if FXKonumu-FHiz<=0 then
                FXKonumu:=0;
            end;
  end;
  Palet:=not palet;
end;

procedure TTank.SetBoyu(const Value: integer);
begin
  FBoyu := Value; Height:=Value; //şimdilik çömezim, böyle yaptım...
end;

procedure TTank.SetEkrandakiKursunSayisi(const Value: integer);
begin
  FEkrandakiKursunSayisi := Value;
end;

procedure TTank.SetEziciGucu(const Value: integer);
begin
  FEziciGucu := Value;
end;

procedure TTank.SetGenisligi(const Value: integer);
begin
  FGenisligi := Value; Width:=Value; //şimdilik çömezim, böyle yaptım...
end;

procedure TTank.SetHasar(const Value: integer);
begin
  FHasar := Value;
end;

procedure TTank.SetHasaraKarsiDayanmaGucu(const Value: integer);
begin
  FHasaraKarsiDayanmaGucu := Value;
end;

procedure TTank.SetHiz(const Value: integer);
begin
  FHiz := Value;
end;

procedure TTank.SetKursunSayisi(const Value: integer);
begin
  FKursunSayisi := Value;
end;

procedure TTank.SetNumarasi(const Value: integer);
begin
  FNumarasi := Value;
end;

procedure TTank.SetSilahGucu(const Value: integer);
begin
  FSilahGucu := Value;
end;

procedure TTank.SetXKonumu(const Value: integer);
begin
  FXKonumu := Value; Left:=Value; //şimdilik çömezim, böyle yaptım...
end;

procedure TTank.SetYKonumu(const Value: integer);
begin
  FYKonumu := Value; Top:=Value; //şimdilik çömezim, böyle yaptım...
end;

procedure TTank.SetYon(const Value: TYonler);
begin
  FYon := Value;
end;

procedure TTank.YoneGoreResimTayinEt;
{$j+}
const
  palet:boolean=true;
begin
  case FYon of
    yKuzey: begin
              if palet then
                picture:=Form1.Image1.Picture
              else
                picture:=form1.Image2.Picture;
            end;
    yGuney: begin
              if palet then
                picture:=form1.Image3.Picture
              else
                picture:=form1.Image4.Picture;
            end;
    yDogu:  begin
              if palet then
                picture:=form1.Image5.Picture
              else
                picture:=form1.Image6.Picture;
            end;
    yBati:  begin
              if palet then
                picture:=form1.Image7.Picture
              else
                picture:=form1.Image8.Picture;
            end;
  end;
end;

end.

Kod: Tümünü seç

unit UThreadTank;

interface

uses
  Classes,UTank,controls,dialogs;

type
  TThreadTank = class(TThread)
  private
    Tank:TTank;
    procedure SenkronizeCalisanProsedur;
    { Private declarations }
  protected
    procedure Execute; override;
  public
  
    constructor
      create(AOwner:TWinControl;X,Y:Integer;AYon:TYonler;AHiz:integer;ABoy,AGenislik:integer;AEziciGucu:integer;AHasaraKarsiDayanmaGucu:integer;ASilahGucu:integer);
    destructor
      destroy;override;
  end;

implementation

uses SysUtils,UAnaUnit;

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure UThreadTank.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ UThreadTank }

constructor TThreadTank.create(AOwner: TWinControl; X, Y: Integer;
  AYon: TYonler; AHiz, ABoy, AGenislik, AEziciGucu,
  AHasaraKarsiDayanmaGucu, ASilahGucu: integer);
begin
  inherited create(false);
  Tank:=TTank.create(AOwner,x,y,AYon,AHiz,ABoy,AGenislik,AEziciGucu,AHasaraKarsiDayanmaGucu,ASilahGucu);
  FreeOnTerminate:=true;
end;

destructor TThreadTank.destroy;
begin
//  form1.Caption:='threadtank.destroy çalıştı';
  Tank.destroy;
  inherited destroy;
end;

procedure TThreadTank.Execute;
begin
  while (not Terminated) do
  begin
    Synchronize(SenkronizeCalisanProsedur);
    Sleep(50);
  end;
  { Place thread code here }
end;

procedure TThreadTank.SenkronizeCalisanProsedur;
begin
  Tank.HareketEttir;
end;

end.
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

Arkadaşlar, programcılık tekniği açısından doğru mudur bilmiyorum ama bişekilde çözdüm problemi... tank nesnesini thread'in destroy bölümünde değil de OnTerminate property'sinin gösterdiği bir prosedür içinde yokediyorum... Problem çıkmıyor... Saygılar, sevgiler...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Cevapla