Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Aufruf von TObject.Free verzögern? (https://www.delphipraxis.net/144836-aufruf-von-tobject-free-verzoegern.html)

Leanahtan 17. Dez 2009 19:47


Aufruf von TObject.Free verzögern?
 
In unserem Projekt gibt es einen Typ TNotifyList zur Verwaltung von Events. Dieser ist Bestandteil der meisten anderen Objekttypen, und wird daher im constructor dieser Typen erfeugt, und im Destructor mit Free wieder freigegeben. Nun gibt es aber eine Möglichkeit, dass eine Methode von TNotifyList noch in einem Schleifendurchlauf hängt, während Free aufgerufen wird, was letztlich zu einem Absturz führt. Da man in einer Methode nicht wirklich überprüfen kann, ob Self nicht schon freigegeben wurde, habe ich mir überlegt, einen eigenen Destructor für TNotifyList zu basteln. Dieser soll zuerst prüfen, ob das Objekt schon zerstört werden darf, und nur dann das Objekt freigeben. Nach Möglichkeit möchte ich dabei nichts an den externen Aufrufen von TNotifyList.free ändern müssen (der Umweg über eine Hilfsmethode TryFree wäre nur die letzte Notlösung).

Ich bin mir jetzt aber nicht so sicher, wie ich das genau machen kann/muss. Wie funktioniert das mit inherited bzw. wie kann ich sicherstellen, dass beim Aufruf von Free das Objekt nur freigegeben wird, wenn eine bestimmte Bedingung erfüllt wurde?

mjustin 17. Dez 2009 20:05

Re: Aufruf von TObject.Free verzögern?
 
Nun, ein Veto oder eine Exception sind in einem Destruktor nicht ganz einfach zu realisieren.

Aber anders herum könnte die TNotifyList ein Flag enthalten, das ihren Status ("arbeitend" / "ruhend") darstellt, und dann abgefragt werden könnte:

Delphi-Quellcode:
while MyNotifyList.IsWorking do
  Application.ProcessMessages;

MyNotifyList.Free;
Zusätzlich kann man noch eine zeitliche Grenze verwenden, nach deren Überschreitung das Free erzwungen wird selbst wenn noch Verarbeitungen stattfinden:

Delphi-Quellcode:
while (MyNotifyList.IsWorking) and (ElapsedTime < MAX_WAIT_TIME) do
  Application.ProcessMessages;

MyNotifyList.Free;
Viele Grüße,

Alter Mann 17. Dez 2009 20:09

Re: Aufruf von TObject.Free verzögern?
 
Hi,

leider schon alles gesagt/geschrieben.

Bis bald.

Leanahtan 17. Dez 2009 20:14

Re: Aufruf von TObject.Free verzögern?
 
Danke für die schnelle Antwort. Also die Idee mit dem Flag hatte ich auch schon, und hab ich auch schonmal so umgesetzt.

Delphi-Quellcode:
  if fNotifyList.RunningEventCalls=0 then
    fNotifyList.Free
  else
    fNotifyList.WantDestroy:=true;
In der Schleife würde dann geprüft, ob die NotifyList zerstört werden soll. Was mich an dieser Lösung etwas stört - eine entsprechende Abfrage wäre dann in fast jedem Destructor nötig, und das sind bei X-Force nicht wenige. Deshalb wollte ich das halt irgendwie zu TNotifyList verlagern (zur Not vielleicht dann doch lieber mit TryFree). Wenn das mit dem Veto im Destructor nicht ganz trivial ist, heißt das ja wenigstens, das meine Frage nicht ganz so dumm ist, wie ich erst gedacht hab.

himitsu 17. Dez 2009 20:40

Re: Aufruf von TObject.Free verzögern?
 
Überschreibe den Destructor und baue dort eine Schleife rein, welche solange wartet, bis das Objekt freigegeben werden darf ... der Destructor wird ja von Free aufgerufen.

Leanahtan 17. Dez 2009 21:03

Re: Aufruf von TObject.Free verzögern?
 
Danke für den Tipp. Leider wird das so wohl auch nicht funktionieren. Das Problem ist, dass besagte For-Schleife letztlich den Aufruf von TNotifyList.Free enthält, und daher nicht weiter abgearbeitet werden kann, wenn man im Destructor wartet :gruebel:
Das lässt sich auch nicht vermeiden, denn die in der Schleife bearbeiteten Events können Skriptfunktionen aufrufen - und was dort gemacht wird, unterliegt nicht mehr der Kontrolle dass Hauptprogramms. Ich werde wohl doch den weg über eine zusätzliche Methode TryFree gehen müssen. Gibt ja in Delphi eine recht brauchbare Suchen&Ersetzen-Funktion.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:48 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz