Computerwissenschaften

Dynamisches Erstellen von Delphi-Komponenten (zur Laufzeit)

Meistens müssen Sie beim Programmieren in Delphi keine Komponente dynamisch erstellen. Wenn Sie eine Komponente in einem Formular ablegen, übernimmt Delphi die Komponentenerstellung automatisch, wenn das Formular erstellt wird. Dieser Artikel beschreibt die korrekte Methode zum programmgesteuerten Erstellen von Komponenten zur Laufzeit.

 

Dynamische Komponentenerstellung

Es gibt zwei Möglichkeiten, Komponenten dynamisch zu erstellen. Eine Möglichkeit besteht darin, ein Formular (oder eine andere TComponent) zum Eigentümer der neuen Komponente zu machen. Dies ist eine gängige Praxis beim Erstellen von Verbundkomponenten, bei denen ein visueller Container die Unterkomponenten erstellt und besitzt. Dadurch wird sichergestellt, dass die neu erstellte Komponente zerstört wird, wenn die besitzende Komponente zerstört wird.

Um eine Instanz (ein Objekt) einer Klasse zu erstellen, rufen Sie deren „Create“ -Methode auf. Der Create-Konstruktor ist eine Klassenmethode. im Gegensatz zu praktisch allen anderen Methoden, auf die Sie bei der Delphi-Programmierung stoßen, bei denen es sich um Objektmethoden handelt.

Beispielsweise deklariert die TComponent den Create-Konstruktor wie folgt:

Konstruktor Create (AOwner: TComponent); virtuell;

Dynamische Erstellung mit Eigentümern
Hier ist ein Beispiel für eine dynamische Erstellung, bei der Self eine TComponent oder ein TComponent-Nachkomme ist (z. B. eine Instanz einer TForm):

mit TTimer.Create (Self)
beginnen
Intervall:=1000;
Aktiviert:=False;
OnTimer:=MyTimerEventHandler;
Ende;

Dynamische Erstellung mit einem expliziten Aufruf zum Freigeben
Die zweite Möglichkeit, eine Komponente zu erstellen, besteht darin, nil als Eigentümer zu verwenden. Beachten Sie, dass Sie in diesem Fall das von Ihnen erstellte Objekt auch explizit freigeben müssen, sobald Sie es nicht mehr benötigen (oder es kommt zu einem Speicherverlust ). Hier ist ein Beispiel für die Verwendung von nil als Eigentümer:

mit TTable.Create (nil) zu tun
versuchen
Database:=’Meinalias‘;
TableName:=’MyTable‘;
Öffnen;
Bearbeiten;
FieldByName (‚Busy‘). AsBoolean:=True;
Post;
endlich
frei;
Ende;

Dynamische Erstellung und Objektreferenzen
Es ist möglich, die beiden vorherigen Beispiele zu erweitern, indem das Ergebnis des Aufrufs „Erstellen“ einer Variablen zugewiesen wird, die lokal zur Methode gehört oder zur Klasse gehört. Dies ist häufig wünschenswert, wenn Verweise auf die Komponente später verwendet werden müssen oder wenn Umfangsprobleme vermieden werden müssen, die möglicherweise durch „With“ -Blöcke verursacht werden. Hier ist der TTimer-Erstellungscode von oben, der eine Feldvariable als Referenz auf das instanziierte TTimer-Objekt verwendet:

FTimer:=TTimer.Create (Self);
mit FTimer
beginnen
Intervall:=1000;
Aktiviert:=False;
OnTimer:=MyInternalTimerEventHandler;
Ende;

In diesem Beispiel ist „FTimer“ eine private Feldvariable des Formulars oder des visuellen Containers (oder was auch immer „Self“ ist). Wenn Sie über Methoden dieser Klasse auf die FTimer-Variable zugreifen, sollten Sie vor der Verwendung überprüfen, ob die Referenz gültig ist. Dies geschieht mit der Funktion „Zugewiesen“ von Delphi:

wenn zugewiesen (FTimer), dann FTimer.Enabled:=True;

Dynamische Erstellung und Objektreferenzen ohne Eigentümer
Eine Variation davon besteht darin, die Komponente ohne Eigentümer zu erstellen, die Referenz jedoch für eine spätere Zerstörung beizubehalten. Der Konstruktionscode für den TTimer würde folgendermaßen aussehen:

FTimer:=TTimer.Create (nil);
mit FTimer
beginnen

enden;

Und der Zerstörungscode (vermutlich im Destruktor des Formulars) würde ungefähr so ​​aussehen:

FTimer.Free;
FTimer:=null;
(*
Oder verwenden Sie die Prozedur FreeAndNil (FTimer), mit der eine Objektreferenz freigegeben und die Referenz durch Null ersetzt wird.
*)

Das Festlegen der Objektreferenz auf Null ist beim Freigeben von Objekten von entscheidender Bedeutung. Der Aufruf von Free überprüft zuerst, ob die Objektreferenz Null ist oder nicht, und wenn dies nicht der Fall ist, ruft er den Destruktor Destroy des Objekts auf.

 

Dynamische Erstellung und lokale Objektreferenzen ohne Eigentümer

Hier ist der TTable-Erstellungscode von oben, der eine lokale Variable als Referenz auf das instanziierte TTable-Objekt verwendet:

localTable:=TTable.Create (nil);
Versuchen Sie es
mit localTable. Beginnen Sie
mit
DataBaseName:=’MyAlias‘;
TableName:=’MyTable‘;
Ende;

// Später, wenn wir den Bereich explizit angeben möchten:
localTable.Open;
localTable.Edit;
localTable.FieldByName (‚Busy‘). AsBoolean:=True;
localTable.Post;
endlich
localTable.Free;
localTable:=nil;
Ende;

Im obigen Beispiel ist „localTable“ eine lokale Variable. die in derselben Methode deklariert wurde, die diesen Code enthält. Beachten Sie, dass es nach dem Freigeben eines Objekts im Allgemeinen eine sehr gute Idee ist, den Verweis auf Null zu setzen.

 

Ein Wort der Warnung

WICHTIG: Mischen Sie einen Aufruf von Free nicht mit der Übergabe eines gültigen Besitzers an den Konstruktor. Alle vorherigen Techniken funktionieren und sind gültig, aber Folgendes sollte in Ihrem Code niemals vorkommen :

mit TTable.Create (self)
versuche

endlich
Free;
Ende;

Das obige Codebeispiel führt zu unnötigen Leistungseinbußen, wirkt sich geringfügig auf den Speicher aus und kann zu schwer zu findenden Fehlern führen. Finde heraus warum.

Hinweis: Wenn eine dynamisch erstellte Komponente einen Eigentümer hat (angegeben durch den AOwner-Parameter des Konstruktors Create), ist dieser Eigentümer für die Zerstörung der Komponente verantwortlich. Andernfalls müssen Sie Free explizit aufrufen, wenn Sie die Komponente nicht mehr benötigen.

Artikel ursprünglich von Mark Miller geschrieben

In Delphi wurde ein Testprogramm erstellt, um die dynamische Erstellung von 1000 Komponenten mit unterschiedlichen anfänglichen Komponentenzahlen zeitlich zu steuern. Das Testprogramm wird unten auf dieser Seite angezeigt. Das Diagramm zeigt eine Reihe von Ergebnissen aus dem Testprogramm, wobei die Zeit verglichen wird, die zum Erstellen von Komponenten sowohl mit als auch ohne Eigentümer benötigt wird. Beachten Sie, dass dies nur ein Teil des Treffers ist. Eine ähnliche Leistungsverzögerung ist zu erwarten, wenn Komponenten zerstört werden. Die Zeit zum dynamischen Erstellen von Komponenten mit Eigentümern ist 1200% bis 107960% langsamer als die zum Erstellen von Komponenten ohne Eigentümer, abhängig von der Anzahl der Komponenten im Formular und der zu erstellenden Komponente.

 

Das Testprogramm

Warnung: Dieses Testprogramm verfolgt und gibt keine Komponenten frei, die ohne Eigentümer erstellt wurden. Wenn diese Komponenten nicht verfolgt und freigegeben werden, spiegeln die für den dynamischen Erstellungscode gemessenen Zeiten die Echtzeit zum dynamischen Erstellen einer Komponente genauer wider.

Quellcode herunterladen

 

Warnung!

Wenn Sie eine Delphi-Komponente dynamisch instanziieren und später explizit freigeben möchten, übergeben Sie immer nil als Eigentümer. Andernfalls können unnötige Risiken sowie Probleme mit der Leistung und der Codewartung entstehen. Lesen Sie den Artikel „Eine Warnung zum dynamischen Instanziieren von Delphi-Komponenten“, um mehr zu erfahren …

Similar Posts

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.