AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi Verzögertes Laden von Komponenten in Delphi 2005
Tutorial durchsuchen
Ansicht
Themen-Optionen

Verzögertes Laden von Komponenten in Delphi 2005

Ein Tutorial von sakura · begonnen am 18. Nov 2004 · letzter Beitrag vom 18. Nov 2004
Tutorial geschlossen
Seite 1 von 2  1 2      
Benutzerbild von sakura
sakura
Registriert seit: 10. Jun 2002
Folgender Text ist eine Übersetzung des Originals von Allen Bauer: Demand-loaded component packages in Delphi 2005.

Allen Bauer hat uns die schriftliche Genehmigung zu dieser Übersetzung gegeben.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#2
  Alt 18. Nov 2004, 09:18
In Delphi 2005 gibt es erstmalig eine neue Art und Weise, in welcher Design-Time Komponenten Packages geladen werden. Hierbei unterscheidet Delphi 2005 zwischen Packages welche sofort, also beim Start von Delphi 2005, geladen werden und Packages welche verzögert geladen werden. Das gibt der IDE die Möglichkeit gezielter die Packages zu laden, welche wirklich benötigt werden und damit die gesamte Startzeit zu verkürzen. Jetzt, wo Delphi 2005 drei Produkte in einem sind, hilft jedes kleine bisschen an Einsparungen. Generell lässt sich sagen, dass die Entscheidung welche Packages, bzw. Gruppen von Packages geladen werden recht einfach zu bestimmen ist. Wenn ein Package geladen wird und dieses seine Komponenten registriert, versucht die IDE festzusstellen, ob dieses Package ein Kandidat für ein verzögertes Laden ist, oder nicht. Es gibt allerdings ein paar Fettnäpfchen in welche man treten kann und welche zu Verwirrungen führen können. Es gibt einige Ausnahmefälle, in welchen die Logik zu Problemen führen kann. Im weiteren Verlauf dieses Artikels werde ich (immer: Allen Bauer) versuchen die Logik zu beschreiben, welche die IDE anwendet um zu bestimmen, ob Packages verzögert geladen werden oder nicht.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#3
  Alt 18. Nov 2004, 09:28
Fange wir mal mit ein paar Annahmen an. In Delphi Win32, wenn man es mal genau betrachtet, ist eine Klassenreferenz eigentlich nicht mehr als ein Pointer (Zeiger) in die virtuelle Methodentabelle (VTM). Die VTM ist im ".text" bzw. ".code" Segment des Modules (.exe, .dll oder Package) gespeichert. Dieses zu verstehen ist die Voraussetzung zur Ermittlung von Informationen des Speicherortes der Implementierung einer Klasse. Die Funktion VirtualQueryEx erleichtert uns das Auffinden des Modules welches die gesuchte Klasse definiert. Man muss nur die Klassenreferenz als Parameter an die Funktion übergeben und erhält die gesuchte Information in einer MEMORY_BASIC_INFORMATION Struktur. Das Feld AllocationBase speichert das Handle (HMODULE) des Modules welches die Klasse implementiert. Dieser Wert kann wiederum an die Funktion GetModuleFileName übergeben werden und denn vollständigen Pfad zum gesuchten Modul zu erhalten.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#4
  Alt 18. Nov 2004, 09:38
Jetzt möchte ich noch definieren, was wir unter einer "Packagegruppe" verstehen. Einfach gesagt ist es ein Paket mit all seinen Abhängigkeiten, sowohl den direkten als auch den indirekten. Mal angenommen: Package A enthält die Packages A, B und C, und A ist das Basis-Package (Root Package), oder anders gesagt, A setzt voraus, dass auch B und C geladen werden. Nun stellt sich die Frage, was ist die Gruppe für Package B? Ganz einfach, es ist einfach Package B. Das liegt daran, dass B nicht voraussetzt, dass A oder C geladen werden damit B läuft. Würde B C voraussetzen, dann würde B's Packagegruppe C beinhalten. Natürlich können weder B noch C das Package A voraussetzen, da wir sonst eine zirkuläre Referenz hätten und dieses ist nicht gestattet ist. Natürlich können jetzt die Packages A, B und C auch durch andere Packagegruppen genutzt werden. Zum Beispiel: Sagen wird, dass Package D auch die Packages B und C voraussetzt. Jetzt haben wir also zwei Packagegruppen. Eine beinhaltet die Packages A, B und C, und die andere beinhaltet die Packages D, B und C. Die jeweiligen Basis Packages sind A und D.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#5
  Alt 18. Nov 2004, 09:50
Jetzt, wo diese beiden Voraussetzungen geklärt sind, wollen wir damit anfangen zu erklären, wie die IDE feststellt welche Packages for verzögertes Laden in Frage kommen. Wenn die IDE auf ein Design-Time Package stößt, dann wird diese meistens verschiedene Run-Time Packages "benötigen", welche ausschließlich die Informationen enthalten, welche zur Laufzeit der Komponenten benötigt werden. (Du hast doch hoffentlich Deine Design-Time Komponenten von den Run-Time Komponenten getrennt... hast Du? Wenn nicht, dann ist das ein Grund für eine spätere Diskussion ) Das Design-Time Package ist der Ort, wo die eigentliche Komponente und die Komponenten-/Eigenschafts- und Auswahleditoren registriert werden. Diese wird durch Aufrufe zu RegisterComponents, RegisterPropertyEditor, RegisterComponentEditor, etc innerhalb der globalen Prozeduren Register erledigt. Es ist wichtig, dass immer die Register Prozedur genutzt wird, um diese Aufgabe zu erledigen damit das verzögerte Laden der Packages unterstützt werden kann. Weitere Informationen dazu gibt es in diesem Blog Eintrag. Um zu ermitteln, ob ein Package verzögert geladen werden kann werden alle Aufrufe zu Prozeduren, welche Komponenten, Eigenschaftseditoren, etc. registrieren überwacht. Es wird darauf geachtet, ob alle Registrierungen sich ausschließlich auf das zu registrierende Package beziehen, oder nicht. Wenn z.B. ein Eigenschaftseditor registriert wird, der sich auf möglicherweise auf eine Komponente ausserhalb des Packages bezieht, so wird dieses Package vom verzögerten Laden ausgeschlossen. Das ist ein wichtiger Punkt.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#6
  Alt 18. Nov 2004, 09:59
Intern erstellt die IDE verschieden Datenbäume, welche während der jeweiligen Registrierungen gefüllt werden. Während jede Komponente/jeder Editor/jede Auswahl registriert wird, vergleicht die IDE diese mit der jeweiligen Packagegruppe. Erinnerst Du Dich an den VirtualQueryEx Trick von oben? Dieser wird genutzt um festzustellen, welches Package welche Komponente/Editor/Auswahl etc. beinhaltet. Solange das Package innerhalb der gleichen Gruppe ist, ist alles in Ordnung. Sollte es einer Referenz gestattet sein nach ausserhalb der Gruppen zu dringen, dann könnte es passieren, dass die Komponente/Editor/Auswahl nicht korrekt geladen wird, wenn diese gebraucht wird. Nehmen wir als Beispiel, dass Du einen Eigenschaftseditor für alle Eigenschaften von Typ TStrings für alle TPersistent-Objekte erstellen willst. Dieses ist eine vollständig "legale" Registrierung, allerdings würde diese das Package vom verzögerten Laden ausschließen. Dieser Ausschluß ist nicht unbedingt eine negative Sache. Es kann durchaus sein, dass Du den von Borland mitgelieferten TString-Eigenschaftseditor mit einem eigenen übergehen willst. Es bedeute einfach, dass Dein Package immer geladen wird, entweder während des Starts von Delphi oder wenn ein Projekt geladen wird, welches das Package nutzt.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#7
  Alt 18. Nov 2004, 10:10
Was kann man jetzt tun, wenn man erreichen will, dass ein Package verzögert geladen wird, dieses aber nicht der Fall ist? Wie kann man feststellen, warum es vom verzögerten Laden ausgeschlossen wurde? Nun ja, während ich dieses Feature eingebaut habe, habe ich mir diese gleichen Fragen gestellt. Also habe ich, neben der Analyselogik auch eine große Log- und Reporting-Logik hinzugefügt. Diese Funktionalität steht jedem Entwickler zur Verfügung. Es gibt zwei Möglichkeiten das Reporting einzuschalten. Eine der Möglichkeiten arbeitet Package-bezogen. Das kann dadurch erreicht werden, indem man die Funktion EnableDemandLoadReport(Detailed: Boolean); aus der Unit DesignIntf innerhalb einer der Register Prozeduren des Design-Time Packages auffruft. Übergibt man den Parameter False, so erhält man nur den Grund, warum das Package ausgeschlosen wurde, übergibt man True, so erhält man einen ausführlichen Report über alle durchgeführten Registrierungsvorgänge. Nachdem das Package vollständig geladen und registriert wurde, erstellt die IDE eine Textdatei welche den gleichen Namen wie das Package trägt mit der Endung .rpt. Diese Datei ist im gleichen Verzeichnis wie auch das Package hinterlegt. Man kann auch globales Reporting einschalten, indem man in der Registry im Schlüssel HKCU\Software\Borland\BDS\3.0\Package Cache einen oder beide der folgenden Werte einträgt:
Code:
Report=1
DetailedReport=1
Diese entsprechen den Aufrufen zu EnableDemandLoadReport mit False bzw. True. Das geniale an der zweiten Lösung ist, dass man somit das Reporting für alle Packages, also auch die Standardpackages von Borland einschaltet.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#8
  Alt 18. Nov 2004, 10:17
Es gibt einige Fälle, in welchen die IDE "verwirrt" ist, welche Packages verzögert geladen werden sollen und welche nicht. Ein solcher Fall ist es zum Beispiel, das ein Design-Time Package ein Run-Time/Design-Time Package benötigt. Das Run-Time/Design-Time Package registriert einige Komponenten und das Design-Time Package die dazugehörigen Editoren und Auswahlelemente. In solchen Fällen gibt es zwei Möglichkeiten. Die bevorzugte Methode ist es die Packages so umzustrukturieren, dass die Design-Time Elemente aus dem Run-Time/Design-Time Package in das "reine" Design-Time Package verschoben werden. Die andere Möglichkeit ist es, den Aufruf ForceDemandLoadState(dlDisable); in das Design-Time Package einzufügen. Das bringt uns auch schon zu einer weiteren neuen globalen Funktion ForceDemandLoadState(). Diese ermöglicht es die automatische Analyselogik der IDE zu umgehen und so unseren Willen durchzusetzen. Es mag Gründe geben, welche die IDE veranlassen ein Package vom verzögerten Laden auszuschließen, man jedoch überzeugt ist, dass das nicht nötig ist. Ein Aufruf zu ForceDemandLoadState(dlEnable); innerhalb der Register Prozedur löst das Problem. Weitere Information hierzu befinden sich in den Kommentaren der Unit DesignIntf.pas.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#9
  Alt 18. Nov 2004, 10:23
Gut, jetzt wo die Packages verzögert geladen werden, wie und wann werden diese eigentlich geladen? Wenn zum Beispiel eine Komponente erstellt wird, dann stellt die IDE fest, dass diese aus eine verzögert geladenem Package kommt und lädt dieses Package "verzögert". Diese geschieht entweder wenn man eine Komponente auf die Designfläche zieht oder wenn man ein Form/Datenmodule/Frame lädt, welches eine solche Komponente beinhaltet. Aber wie sieht es mit den Editoren und Auswahlen aus? All diese Editoren/Komponenten/Auswahlen sind Komponentenabhängig, d.h. dass diese immer voraussetzen, dass eine Kompontente existieren muss, damit diese geladen werden. Da diese erst benötigt werden, wenn ein Package welche diese benötigt geladen wird, werden auch diese automatisch gleichzeitig verzögert geladen.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#10
  Alt 18. Nov 2004, 10:24
Es gibt noch mehr Punkte, welche das verzögerte Laden von Packages beeinflussen, sowohl in der Überwachung als auch in der Art und Weise wie der Status und die Palette arbeiten, das jedoch ist für einen weiteren Blogeintrag.
Daniel W.
 
Tutorial geschlossen
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:24 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