dizi ve diziyi kullann threadları yokederken access violatio

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:

dizi ve diziyi kullann threadları yokederken access violatio

Mesaj gönderen huseyinkucuk »

Selamlar... Arkadaşlar, şimdi bi tane TTank diye bi sınıf tanımladım, sonra TTankinThreadi diye bi sınıf tanımladım... Unit1'de de bi düğme var, buna basınca Tanklar (array of TTank) ve TankinThreadi (array of TTank global) değişkenlerime Setlengt(tanklar, high(tanklar)) ve TankinThreadi(tanklar,high(tanklar)) yapıyor ve kapat düğmemde de ikisini de kapatıyor ve Setlengt ile aşağıdaki kodlarda anlayacağınız gibi kapatıyor... Şimdi benim anlamadığım şu... Açık olan tanklar (ekranda gördüklerimi anlatıyorum) tek tek kapanıyor ama ara sıra access violation hatası veriyor... Bunun sebebi ne olabilir... Şimdiden teşekkür ederim... Kodlar aşağıda...

Kod: Tümünü seç

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls,Utank,UThreadTank;

....
....
....


var
  Tank:Array of TTank;
  TankinThreadi:Array of TThreadTank;
procedure TForm1.Button1Click(Sender: TObject); //Tank ve threadini yaratan düğme...
var
  x,y,hiz:integer;
  Yon:TTankinYonu;
begin
  setlength(tank,high(tank)+2);
  setLength(TankinThreadi,high(tank)+1);
  form1.Caption:='high(tank)='+inttostr(high(tank))+' high(tankinthreadi)='+inttostr(high(tankinthreadi));
  Randomize;
  x:=RandomRange(0,form1.ClientWidth-105); //105 resmin genişliği...
  y:=randomrange(0,form1.Height-105); //105 resmin yüksekliği...
  case random(4) of
    0:Yon:=tyKuzey;
    1:Yon:=tyGuney;
    2:Yon:=tyDogu;
    3:Yon:=tyBati;
  end;
  Tank[high(tank)]:=TTank.create(form1,x,y,Yon,10);
  Tank[high(tank)].Tag:=high(tank);
  TankinThreadi[high(tank)]:=TThreadTank.create(Tank[high(tank)]);
  TankinThreadi[high(tank)].Priority:=tpLowest;
//  showmessage(inttostr(high(tank)));
end;

procedure TForm1.Button2Click(Sender: TObject); //tank ve threadini kapatan düğme
begin
  if high(tank)<0 then
    exit;
  TankinThreadi[high(tank)].Terminate;
  Tank[high(tank)].Free;
  Setlength(TankinThreadi,high(tank));
  Setlength(Tank,high(tank));
form1.Caption:='high(tank)='+inttostr(high(tank))+' high(tankinthreadi)='+inttostr(high(tankinthreadi));
end;

end.

Kod: Tümünü seç

unit UTank;

interface

Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,extctrls;

Type
  TTankinYonu=(tyKuzey,tyGuney,tyDogu,tyBati);
  TCarpmaYonu=(cyKuzeyden,cyGuneyden,cyDogudan,cyBatidan,cyYok);

///////////////////////////////////////////
Type TTank=class(TImage)
private
  FTankinXKonumu:integer;
  FTankinYKonumu:integer;
  FTankinYonu:TTankinYonu;
  FTankinHizi:integer;
  FTankinBenzini:integer;
  FTankinHasari:integer;
  FTankinAtesGucu:integer;
  FTankinAtesHizi:integer;
  FTankinEziciGucu:integer;
  FTankinAtmisOlduguAtesSayisi:integer;
  FTankinAtabilecegiAtesSayisi:integer;
  FKuzeyResimAdresi1:string;
  FGuneyResimAdresi1:string;
  FDoguResimAdresi1:string;
  FBatiResimAdresi1:string;
  FKuzeyResimAdresi2:string;
  FGuneyResimAdresi2:string;
  FDoguResimAdresi2:string;
  FBatiResimAdresi2:string;
  FTankinGenisligi:integer;
  FTankinYuksekligi:integer;
  FCarpaHangiYonden:TCarpmaYonu;
    procedure WTankinXKonumu(const Value: integer);
    procedure WTankinYKonumu(const Value: integer);
    procedure WTankinYonu(const Value: TTankinYonu);
    procedure Wtankinhizi(const Value: integer);
    procedure YoneGoreResimTayinEt;

//protected
  
public
  property TankinXKonumu:integer
    read FTankinXKonumu write WTankinXKonumu;
  Property TankinYKonumu:integer
    read FTankinYKonumu write WTankinYKonumu;
  Property TankinYonu:TTankinYonu
    read FTankinYonu write WTankinYonu;
  Property TankinHizi:integer
    read FTankinHizi write Wtankinhizi;
  constructor
    create(AOwner:TWinControl;x,y:integer;ATankinYonu:TTankinYonu;ATankinHizi:integer);
  destructor
    destroy;override;
end;
////////////////////////////////////////////
implementation

{ TTank }


///////////////////yaratma ve yok etme bölümleri//////////

//yaratma...
constructor TTank.create(AOwner:TWincontrol;x, y: integer;ATankinYonu:TTankinYonu;ATankinHizi:integer);
begin
  inherited create(AOwner);
  Parent:=AOwner;
  FGuneyResimAdresi1:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank1.bmp';
  FGuneyResimAdresi2:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank1-2.bmp';
  FBatiResimAdresi1:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank2.bmp';
  FBatiResimAdresi2:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank2-2.bmp';
  FKuzeyResimAdresi1:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank3.bmp';
  FKuzeyResimAdresi2:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank3-2.bmp';
  FDoguResimAdresi1:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank4.bmp';
  FDoguResimAdresi2:='C:\Documents and Settings\HK\Desktop\Örneklerim-Çalışmalarım\Thread ile Oraya Buraya Giden Çarpışan Tanklar Yapmaya Çalışıyorum\Tank Resimleri\tank4-2.bmp';
  Height:=20;
  Width:=20;

  FTankinXKonumu:=x;
  FTankinYKonumu:=y;
  FTankinYonu:=ATankinYonu;
  FTankinHizi:=ATankinHizi;
  FCarpaHangiYonden:=cyYok;
  Left:=FTankinXKonumu;
  Top:=FTankinYKonumu;
  Stretch:=True;
  Transparent:=true;
  YoneGoreResimTayinEt;
end;

//Yoketme...
destructor TTank.destroy;
begin
  //showmessage('destroy oluyoz, iyi mi?');  //tanklar varken formu kapatınca yine bu çalışıyo ve showmessage olmayınca kapanırken hata veriyor...
//  Free;
  inherited destroy;
end;
///////////////////////////////////////////////////////////



procedure TTank.Wtankinhizi(const Value: integer);
begin
  FTankinHizi := Value;
end;

procedure TTank.WTankinXKonumu(const value:integer);
begin
  FTankinXKonumu := Value;
  Left:=FTankinXKonumu;
end;

procedure TTank.WTankinYKonumu(const Value: integer);
begin
  FTankinYKonumu := Value;
  Top:=FTankinYKonumu;
end;

procedure TTank.WTankinYonu(const Value: TTankinYonu);
begin
  FTankinYonu := Value;
  YoneGoreResimTayinEt;
end;


procedure TTank.YoneGoreResimTayinEt;
begin
  if FTankinYonu=tyKuzey then
    picture.LoadFromFile(FKuzeyResimAdresi1)
  else
    if FTankinYonu=tyGuney then
      picture.LoadFromFile(FGuneyResimAdresi1)
    else
      if FTankinYonu=tyDogu then
        picture.LoadFromFile(FDoguResimAdresi1)
      else
        if Ftankinyonu=tyBati then
          picture.LoadFromFile(FBatiResimAdresi1);
  Refresh;
end;

end.

Kod: Tümünü seç

unit UThreadTank;

interface

uses
  Classes,UTank,dialogs;

type
  TThreadTank = class(TThread)
  private
    FTank:TTank;
    { Private declarations }
  protected
    procedure Execute; override;
    procedure DegeriDondurenProcedure;
  public
    constructor create(ATank:TTank);
  end;

implementation

uses SysUtils;

{ 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 TThreadTank.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ TThreadTank }

constructor TThreadTank.create(ATank: TTank);
begin
  inherited create(false);
  FreeOnTerminate:=true;
  FTank:=ATank;
end;


procedure TThreadTank.DegeriDondurenProcedure;
begin
  if FTank.TankinYonu=tyKuzey then
    begin
      if FTank.TankinYKonumu-5<0 then
        begin
          FTank.TankinYonu:=tyGuney;
          exit;
        end;
      FTank.TankinYKonumu:=FTank.TankinYKonumu-5;

    end
    else
    if FTank.TankinYonu=tyGuney then
      begin
        if FTank.TankinYKonumu+FTank.Height+5>FTank.Parent.ClientHeight then
        begin
          FTank.TankinYonu:=tyKuzey;
          exit;
        end;
        FTank.TankinYKonumu:=FTank.TankinYKonumu+5;

      end
      else
        if FTank.TankinYonu=tyDogu then
          begin
            if FTank.TankinXKonumu+FTank.Width+5>FTank.Parent.ClientWidth then
            begin
              FTank.TankinYonu:=tyBati;
              exit;
            end;
            FTank.TankinXKonumu:=FTank.TankinXKonumu+5;

          end
          else
            if FTank.TankinYonu=tyBati then
              begin
                if FTank.TankinXKonumu-5<0 then
                begin
                  FTank.TankinYonu:=tyDogu;
                  exit;
                end;
                FTank.TankinXKonumu:=FTank.TankinXKonumu-5;
              end;

end;





procedure TThreadTank.Execute;
begin
  while (not terminated) do
  begin
    Synchronize(DegeriDondurenProcedure);
    FTank.Refresh;
    Sleep(100);
  end;
    { Place thread code here }
end;


end.
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

Threadlerin kullandıkları ortak kaynaklar üzerinde okuma/yazma yaparken criticalsection lar içinde kullan. Böylece yapılan işlem başka bir thread tarafından bölünmez(atomik olur) ve hafıza işlemlerinde hata çıkması engellemiş olursun.
Kullanıcı avatarı
Kuri_YJ
Moderator
Mesajlar: 2248
Kayıt: 06 Ağu 2003 12:07
Konum: İstanbul
İletişim:

Mesaj gönderen Kuri_YJ »

Selamlar,

Unidefined'ın söylediklerine ek olarak Thread-Safe şeklinde kullanım yapın. Değişkenlerinizi her Thread Procedure'unde (Global Değişkenler kullanmaktan kaçının) yerel olarak tanımlayıp kullanın, aksi halde bir Thread okuma yaparken diğeri yazma yapabilir ve bu arada Access Violation alabilirsiniz.

Kolay Gelsin
Kuri Yalnız Jedi
Harbi Özgürlük İçin Pisi http://www.pisilinux.org/
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... Bu söylediklerinizin ne anlama geldiğini tam anlamış değilim ama "thread'lerin aynı hafızaya aynı anda yazmaya/aynı hafızayı okumaya çalışmaları bu hatayı verebilir" ifadeleriniz bana mantıklı geldi... Teşekkürler...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

huseyinkucuk yazdı:arkadaşlar, teşekkür ederim... Bu söylediklerinizin ne anlama geldiğini tam anlamış değilim ama "thread'lerin aynı hafızaya aynı anda yazmaya/aynı hafızayı okumaya çalışmaları bu hatayı verebilir" ifadeleriniz bana mantıklı geldi... Teşekkürler...
Aslında tam öyle değil. Tek cpu'lu mimaride iki thread tam anlamıyla aynı anda zaten işlem göremez. Bunun için aynı kaynağın 2 thread tarafından kullanılmasıda söz konusu değil. İşletim sistemi, çok hızlı olarak vardiyalı şekilde threadlere işlem gördürtür.
Burda hatayı yaratan durum, ortak bir datanın thread tarafından yazılırken işlemin yarıda kesilmesi ve ilgili datanın tam yazılmamasından dolayı o kaynağı okuyan diğer threadin o datayı hatalı olarak okumasına neden olmasıdır. Bunun için yazma ve okuma işlemi atomik olarak yapman gerekir. Bunun yoluda critical sectionlardır.(en azından benim bildiğim yolu)

Kuri abim gereksiz yere global değişken kullanmamnı tavsiye etmeside şu yüzden: Yerel değişkenler stack denen yapıda saklanır ve threadlerin stackları kendine münhasırdır. Onun için datayı başka thread parmaklayamaz ve güvende olur.
Kullanıcı avatarı
huseyinkucuk
Üye
Mesajlar: 142
Kayıt: 29 Nis 2005 10:03
Konum: İstanbul
İletişim:

Mesaj gönderen huseyinkucuk »

(ilk sorunum dışında ayrı bir sorun ve soru bu) Arkadaşlar... TEditi ata sınıf alan TTank diye bi sınıf yaptım... (pek bi özellik eklemedim, aslında hiç bi özellik eklemedim desem yeri var) Sonra TThreadDeneme diye bi Thread sınıfı tanımladım... Bu TThreadDeneme sınıfının içinde (aşağıdaki kodda da göreceğiniz gibi) yaptığım sınıftan bir nesne tanımladım, bu nesne sürekli sağa doğru gidiyor ve formun sonuna geldiği zaman yok olması gerekiyor... Ben düşümdüm ki; TTank nesnesini TThreadDeneme nesnesinin private bölümünde tanımladığıma göre TThreadDeneme nesnesi yok olunca TTank nesnesi de yok olur diye düşündüm... Ama olmadı, formun en sağında durdu öylecene TTank'tan türetilmiş nesne(ler).
Sonra TThreadDeneme.Destroy içine TTankNesnesi.Free yaptım, hata verdi, TTanknesnesi.destroy yaptım, hata verdi. Yapamadım, hatam nedir acaba? Yardımcı olursanız sevinirim... Yazdığım Kodlar şunlar;

Kod:

unit UTankNesnesi;

interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,stdctrls;
type
TTank=Class(TEdit)
private
FXKoordinati,FYKoordinati:integer;
procedure WXKoordinati(const Value: integer);
procedure WYKoordinati(const Value: integer);
public
property XKoordinati:integer read FXKoordinati write WXKoordinati;
property YKoordinati:integer read FYKoordinati write WYKoordinati;
constructor Create(AOwner:TWinControl;x,y:integer);
destructor destroy;override;
end;
implementation


{ TTank }


constructor TTank.Create(AOwner: TWinControl; x, y: integer);
begin
inherited create(AOwner);
Parent:=AOwner;
FXKoordinati:=x; Left:=FXKoordinati;
FYKoordinati:=y; Top:=FYKoordinati;
end;

destructor TTank.destroy;
begin
inherited destroy;
end;

procedure TTank.WXKoordinati(const Value: integer);
begin
FXKoordinati := Value;
Left:=FXKoordinati;
end;

procedure TTank.WYKoordinati(const Value: integer);
begin
FYKoordinati := Value;
Top:=FYKoordinati;
end;

end.


Kod:

unit UThread;

interface

uses
Classes,Controls,UTankNesnesi;

type
TThreadDeneme = class(TThread)
private
MyEdit:TTank;
FOwner:TWinControl;
procedure EsasProsedur;
{ Private declarations }
public
constructor create(AOwner:TWinControl;x,y:integer);
destructor destroy;override;
protected
procedure Execute; override;
end;

implementation

{ 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 TThreadDeneme.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ TThreadDeneme }


constructor TThreadDeneme.create(AOwner: TWinControl; x, y: integer);
begin
inherited create(false);
FOwner:=AOwner;
MyEdit:=TTank.Create(AOwner,x,y);
FreeOnTerminate:=true;
end;



destructor TThreadDeneme.destroy;
begin
MyEdit.destroy;
inherited destroy;
end;

procedure TThreadDeneme.EsasProsedur;
begin
MyEdit.XKoordinati:=MyEdit.XKoordinati+1;

end;

procedure TThreadDeneme.Execute;
begin
while (not terminated) do
begin
Synchronize(EsasProsedur);
if (MyEdit.XKoordinati+MyEdit.Width)>=FOwner.ClientWidth then
exit;
end;
{ Place thread code here }
end;

end.



Kod:

unit UAnaUnit;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
Editim:TThreadDeneme;
begin
Editim:=TThreadDeneme.create(application.MainForm,100,100);
Editim.Priority:=tpLowest;
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 »

tamamdır arkadaşlar, çözdüm... Nesneyi 'EsasProsedur' içinde yokediyorum... Yine de destroy içinde niye yokedemediğimi anlamış değilim... Herkese kolay gelsin...
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 »

Aslında kodunda görünüşte bir sorun yok. Bir ara denemeye çalışayım. Esasprosedur içinde yoketmemen lazım.
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 @coderlord... Umarım haklısındır... Kolay gelsin herkese...
29.04.2005 tarihi itibariyle Delphi öğrenmeye başlayan yeni bir kullanıcı sayılabilirim.
Cevapla