[ FranjoZG @ 22.10.2020. 15:02 ] @
Delphi XE 10

Problem je što se destructor klase tMaster ne pozove.
U main programu koristim interface iAdresar što je iSynhRoot, njegov propety Master i proceduru Execute.
Provjerio sam u kodu, nigdje nemam npr Varijabla1 := iAdresar.Master
tAdresar.fMaster: IMaster kreiram u konstruktoru tAdresar, a oslobodio bih ga u Destructoru tAdresara. Što radim pogrešno?


Imam interface i klasu:
Code:

    iMaster=interface
      ...
   end;

   tMaster=class(TInterfacedObject, iMaster)
      constructor Create; 
      destructor Destroy; override;
   private
      ...
   end;

   iSynhRoot=interface
      function getMaster: iMaster;
      procedure setMaster(const Value: iMaster);
      property Master: iMaster read getMaster write setMaster;
      procedure Execute;    
   end;

   tAdresar=class(TInterfacedObject, iSynhRoot)
      constructor Create(ParentForProgress: tWinControl=nil);
      destructor Destroy; override;
   private
      fMaster: iMaster;
      function getMaster: iMaster;
      procedure setMaster(const Value: iMaster);
   public
      property Master: iMaster read getMaster write setMaster;
      procedure Execute;   
   end;

...
constructor tAdresar.Create(ParentForProgress: tWinControl); // jedino mjesto gdje se kreira Master
begin
   inherited Create;
   
   Master := tMaster.Create;
   ...
end;

destructor tAdresar.Destroy; 
begin
  Master := nil; // ovo bi trebalo pozvati destructor, ali ga ne pozove.
  inherited;
end;

[ savkic @ 22.10.2020. 17:11 ] @
Dodaj, TMaster._AddRef i _Release funkcije, pusti program kroz debugger i prati kad se pozivaju.
Alternativno prati TMaster.RefCount.
[ _deran_ @ 23.10.2020. 07:54 ] @
Kako koristiš tAdresar?
Meni radi i kad je kao interface (bez free naravno)

Ako ti je varijabla tipa tAdresar a ne interface, neće se automatski pozvati destroy

Code:

var adr1:tAdresar;
    adr2:iSynhRoot;
begin

  adr1 := tAdresar.Create();
  adr1.Free;

  adr2 := tAdresar.Create();
  
end;

[ FranjoZG @ 23.10.2020. 08:13 ] @
Hvala na pomoći. Koristim tAdresar samo kao interface. Imam 10-tak različith klasa, sa istim iterface-om.
Pokušat ću ovo što kaže savkić. Znam da TMaster.RefCount mora biti 0 da bi se pozvao Destroy. Tražio sam po programu i nemam nigdje drugdje varijablu koja koristi isit interface zato mi i nije jasno što se događa i zašto se ne poziva Destroy.
[ _deran_ @ 23.10.2020. 08:52 ] @
Verovatno negde još kreiraš instancu, proveri sa _AddRef što Savkić kaže...

Ovaj kod radi:

Code:

unit Unit1;

interface

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

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

var
  Form1: TForm1;


  type
   iMaster=interface

   end;

   tMaster=class(TInterfacedObject, iMaster)
      constructor Create; 
      destructor Destroy; override;
   private

   end;

   iSynhRoot=interface
      function getMaster: iMaster;
      procedure setMaster(const Value: iMaster);
      property Master: iMaster read getMaster write setMaster;
      procedure Execute;    
   end;

   tAdresar=class(TInterfacedObject, iSynhRoot)
      constructor Create(ParentForProgress: tWinControl=nil);
      destructor Destroy; override;
   private
      fMaster: iMaster;
      function getMaster: iMaster;
      procedure setMaster(const Value: iMaster);
   public
      property Master: iMaster read getMaster write setMaster;
      procedure Execute;   
   end;


implementation

{$R *.dfm}

constructor tAdresar.Create(ParentForProgress: tWinControl); // jedino mjesto gdje se kreira Master
begin
   inherited Create;
   Master := tMaster.Create;
end;

destructor tAdresar.Destroy;
begin
  Master := nil; // ovo bi trebalo pozvati destructor, ali ga ne pozove.
  inherited;
end;

{ tMaster }

constructor tMaster.Create;
begin
//
end;

destructor tMaster.Destroy;
begin
  //
  inherited;
end;

procedure tAdresar.Execute;
begin
  //
end;

function tAdresar.getMaster: iMaster;
begin
 Result := fMaster;
end;

procedure tAdresar.setMaster(const Value: iMaster);
begin
  fMaster := value;
end;

procedure TForm1.Button1Click(Sender: TObject);
var adr1:tAdresar;
    adr2:iSynhRoot;
begin

  adr1 := tAdresar.Create();
  adr1.Free;

  adr2 := tAdresar.Create();

end;

end.
[ FranjoZG @ 26.10.2020. 08:42 ] @
Nisam uspio riješiti problem sa Masterom, ne pozove se Destroy klase. Odustao sam i napravio preko objekta, tj. izbacio interface.
Nisam napomenuo, možda ima ulogu, sve koristim u tasku:
Code:

         // ALaTaks ke tList<tMyTask>; tMyTask = klasa u kojoj pamtim parametre potrebne za svaki posao posebno 
         LAllTaks[adri].Pokusaj := LAllTaks[adri].Pokusaj+1;
         LAllTaks[adri].Task := tTask.Create(procedure
            var AdrTr: iSynhRoot;
            begin
               AdrTr := tAdresar.Create; // u Create se postavljaju svi parametri i kreira Master
               AdrTr.Master.LastDateExport := LastAdresarExport; // datum zadnje exporta
               AdrTr.Master.EndProc := EndedTask; // procedura koja se poziva iz Master.Free kada je posao završen. Procedura je u Main formi i pozivam ju sa Synchronize
               AdrTr.Master.TaskName := 'NazivPosla'; // podatak koji se šalje u "EndedTask" kako bih znao o kojem poslu se radi
               AdrTr.Master.Progress := LAllTaks[adri].ProgressBar; // progress bar koji na main formi pokazuje izvršenje posla
               AdrTr.Execute; // procedura u kojoj se sav posao obavlja
            end);  
         LAllTaks[adri].Task.Start;   


LAllTaks = tList<MyTask> gdje je MyTask klasa koja sadrži potrebne podatke za svaki posao

Kada sam izbacio interface za Master i stavio objekt, u Destroy tAdresara pozivam: fMaster.Free i sve se uredno izvrši.
Provjerio sam cijeli kod, nigdje ne koristim varijablu koja pokazuje na interface Mastera. Definirana je u private AdrTr i pristupam joj samo preko propery-a AdrTr.Master.

Izbrojao sam broj poziva Master.Create i Master.Destroy, jednak je.
[ savkic @ 26.10.2020. 13:21 ] @
Delphi mozda implicitno dodaje pozive, jedini siguran put je da pustis kroz debugger i pratis sta se i kad desava.