![]() |
Delphi-Version: 10 Berlin
Application.CreateForm in einem Thread
Ist es generell eine schlechte Idee ein Application.CreateForm in einem TTask aufzurufen? Oder bringt das keinerlei Vorteile?
Ich versuche gerade ein bisschen die Wartezeiten optimieren und es gibt genau ein Formular welches etwa 2 Sekunden braucht, bis es komplett erzeugt wurde. Es ist nur eine Komponente drauf, die ich hier im Forum gefunden habe. |
AW: Application.CreateForm in einem Thread
"Ist es generell eine schlechte Idee ... *VCL* und *Thread*?"
Antwort: Ja. |
AW: Application.CreateForm in einem Thread
Eine Komponente, die 2 Sekunden braucht um sich zu erzeugen? Wenn du die hier gefunden hast, dann poste doch mal den Link.
|
AW: Application.CreateForm in einem Thread
Was allerdings wirklich spannend sein kann: Warum läd dein Formular ca 2 Sekunden? Gibt es da vielleicht noch Möglichkeiten die "Datenbeschaffung" (ich erlaube mir das mal so zwischen den Zeilen zu lesen...:thumb:) und tatsächliche Oberflächenobjektinstanziierung zu trennen? :P
Brighty :) [Edit] Hobbycoder, da hatten wir wohl den selben unterschwelligen Gedanken :D [/Edit] |
AW: Application.CreateForm in einem Thread
Aber das ist doch nicht abwegig viel?
Ich habe nie mit einem Profiler wirklich nachgemessen, aber eine unserer Anwendungen braucht auch mehrere Sekunden für den Aufbau des Hauptformulars. Ist in der IDE im Formular-Designer für die einzelnen Frames nicht anders, in der Summe erscheint mir das plausibel... |
AW: Application.CreateForm in einem Thread
Mein Formular enthält nur eine einzige Komponente die man wie gesagt hier im Forum findet. Es ist eine Art TreeView mit CheckBoxen.
Ich habe schon überlegt die mit einer VirtualStringTree selber neu zu erstellen aber dafür fehlt es mir an Grundkenntnissen bezüglich VirtualStringTree. |
AW: Application.CreateForm in einem Thread
Zitat:
Aber das erzeugen "einer" Komponente zur Laufzeit....ist vielleicht doch "möglicherweise" etwas zu viel. (Ich sage bewusst Möglicherweise). Zitat:
Hast eine Datenbindung ggf. in der IDE bereits getätigt? Das könnte natürlich dazu führen, dass die Komponente währende des Erzeugens bereits Daten einliest, und das könnte die Ursache sein. Versucht dann doch mal, die Daten etwas später bereit zustellen. Innerhalb der Anwendung kannst du evtl. das Laden der Daten dann nämlich im Thread machen, und sie dann an die Komponente binden / übergeben. Solange wir aber nicht wissen, worum es geht, sind das alles Blicke in die Glaskugel. |
AW: Application.CreateForm in einem Thread
Zitat:
|
AW: Application.CreateForm in einem Thread
Es sind die hier erwähnten GTRO-Controls.
![]() ![]() Zu deiner spezifischen Frage: in der IDE ist der Desktop standardmäßig eingestellt. Soweit ich herausfinden konnte dauert das Erstellen der Einträge lange, wenn die Objekt-Typen auf [otFolders,otNonFolders,otHidden] stehen. Sind sie leer, wird das Formular recht schnell aufgebaut. Daher auch meine Idee das mit einer VirtualStringList nachzubauen aber das Grundwissen fehlt. |
AW: Application.CreateForm in einem Thread
Zitat:
Wenn ich heute abend noch Zeit habe, dann bastele ich dir mal etwas ganz kleines zusammen bei dem du wenigstens mal die Nodes erstellen und die Texte anzeigen lassen kannst. Den CheckSupport (also Anzeige von CheckBoxen) kann man dann noch nachträglich hinzufügen. Woher kommen denn deine Daten? Kannst du evtl. mal eine kleine Struktur aufzeigen, wie die Daten aussehen? Welche Properties gibt es? Ich würde dir auf jeden Fall empfehlen, dir den VST anzuschauen und dir das Wissen darüber anzueignen. Die Komponente ist Gold wert und um ein Vielfaches schneller als andere Komponenten. Ich benutze sie nur noch und bin seit dem Umstieg begeistert. Allerdings arbeite ich mittlerweile schon seit bestimmt 3 Jahren damit. Da kennt man so ziemlich alles vom VST und hat auch schon fast alles damit gemacht. Und ich denke, dass es bestimmt noch einige andere User hier im Forum gibt, die dir ebenfalls gerne beim Lernen im Umgang mit dem VST helfen werden. |
AW: Application.CreateForm in einem Thread
Das mit den Daten ist ganz einfach. Es gibt ein Root-Verzeichnis welches man angeben kann und das wird dann eingelesen.
Wenn man dann neben einem Verzeichnis auf den kleinen Pfeil klickt, wird der Eintrag expandiert und ich sehe den Inhalt der dann erst eingelesen wird, wenn man expandiert. Es gibt demnach keine speziellen Daten. Es ist einfach nur eine Anzeige für eine Verzeichnisstruktur. Soweit ich sehen kann gibt es hier keine speziellen Properties auf dass man einstellen kann, ob man Verzeichnisse, Daten und versteckte Inhalte sehen möchte. |
AW: Application.CreateForm in einem Thread
Also könnte man das Beispiel mit dem Aufbau eines Verzeichnisbaumes vom Laufwerk C: durchführen? Ich schau mal ob ich die Zeit dazu finde und poste dementsprechend mal etwas.
|
AW: Application.CreateForm in einem Thread
Ja ganz genau. Wenn das mit einem Verzeichnis funktioniert dann funktioniert das auch mit allen anderen.
Was ich meine entspricht etwa dem auf dem Bild hier. Nur mit CheckBoxen und Dateien. Ordnergröße wäre toll ist aber kein Muss. ![]() Das kann die Komponente hier aus dem Forum ja gut nur sie ist sehr, sehr langsam. |
AW: Application.CreateForm in einem Thread
Für eine Anzeige der enthaltenen Dateien und Ordnergrößen muß auf jeden Fall das komplette Verzeichnis eingelesen werden und das Dauert definitiv etwas.
Will man nur erstmal das Rootverzeichnis anzeigen und lädt die Unterknoten nach, wenn man aufklappt, dann muß man nur das eine Verzeichnis komplett einlesen und in den Unterzeichnissen nur je die erste Datei/Unterverzeichnis einlesen, um zu wissen, ob man das [+] vor der ersten Ebene der jeweiligen Unterverzeichnissen darstellen muß. Allerdings kann man das Einlesen auch in einem Thread oder notfalls Stückchenweise in einem Timer erledigen und dann regelmäßig die Daten im Baum/TreeView aktualisieren. Ist der TreeView zu langsam, vorallem bei vielen Daten, dann den Baum intern komplett einlesen und nur den jeweils sichbaren Teil in den TreeView laden, also nur die aufgeklappten Teile. ![]() ![]() |
AW: Application.CreateForm in einem Thread
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo zusammen,
ich habe jetzt mal ein kleines Demo-Projekt zusammengebastelt und auch mit ein paar Kommentaren versehen. Natürlich wird hier nur ein ganz kleiner Teil der Funktionen des VST gezeigt. Aber für den Einstieg sollte das erst einmal reichen. Wenn du das problemlos programmieren kannst, dann kannst du dich an die tieferen Funktionen des VST wagen. Ich habe in dem Beispiel jetzt keinen Wert darauf gelegt alles in einen Thread auszulagern. In meinem Fall hat das alles sehr schnell funktioniert, sodass ich nicht die Notwendigkeit dafür gesehen habe. Zudem ist es ja erstmal nur ein kleines Projekt zum Testen. Das Auslagern in einen Thread sollte das kleinste Problem sein. Auch ist der Code vielleicht nicht zu 100% optimiert, aber auch hier ... es ist ein Demo-Projekt. Im Anhang habe ich jetzt mal die Release Variante des Projekts als Exe dringelassen falls das jemand nicht kompilieren kann. Erstellt wurde das Projekt mit Delphi 10 Seattle. Viel Spaß beim Probieren @SneakyBagels und auch alle Anderen die sich mal mit dem VST beschäftigen wollen. Wenn Rückfragen aufkommen, dann einfach fragen. Ich denke es gibt auch noch divere andere User die hier weiterhelfen können wenn ich mal keine Zeit habe. :wink: Anhang 47301 |
AW: Application.CreateForm in einem Thread
Ich habe gerade mal versucht hiermit ShellIcons anzeigen zu lassen. Klappt auch aber das zieht die Performance total in den Keller
Delphi-Quellcode:
procedure TfrmDirectoryBrowser.FormCreate(Sender: TObject);
var SysIL: HIMAGELIST; Info: TSHFileInfo; SmallImages: TImageList; begin SmallImages := TImageList.Create(Self); SysIL := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON); if SysIL <> 0 then begin SmallImages.Handle := SysIL; SmallImages.ShareImages := True; vstDirectoryBrowser.Images := SmallImages; end; ..... end; procedure TfrmDirectoryBrowser.vstDirectoryBrowserGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); var NodeData: PDirectory; Info: TSHFileInfo; begin NodeData := Sender.GetNodeData(Node); if NodeData^.iIconIndex = -1 then begin SHGetFileInfo(PChar(NodeData^.FullPath), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON); NodeData^.iIconIndex := Info.iIcon; end; ImageIndex := NodeData^.iIconIndex; end; |
AW: Application.CreateForm in einem Thread
Hallo SneakyBagel,
letzter Beitrag für heute :-D Du machst da noch etwas falsch. Du darfst die ShellIcons nur 1x laden. Also z.B. in der LoadDirectories Methode. Spendiere der TDirectory Klasse dann zusätzlich noch eine Property ImageIndex. Beim Auslesen der Verzeichnisse lädtst du dann nur noch 1x das Icon. Im GetImageIndex Event gibst du dem Tree immer nur noch den Index des Icons in der ImageList aus dem NodeData Object. Das dürfte die Performance erheblich verbessern. EDIT: Wohoo. Passt gerade als Abschluss für heute (oh Moment, wir haben ja schon "morgen"). Der 1000. Beitrag ist gefallen. :cyclops: |
AW: Application.CreateForm in einem Thread
Ok dann für morgen
Delphi-Quellcode:
Angezeigt bekomme ich zwar ein Icon, aber für alle Nodes dasselbe. Ein ganz komisches, teils grünes mit Anführungszeichen.
if (FindFirst(FFullPath + '*', faAnyFile, SR) = 0) then
begin try repeat if ((SR.Name <> '.') and (SR.Name <> '..')) then // and ((SR.Attr and faDirectory) = faDirectory)) then begin Dir := TDirectory.Create(Format('%s%s\', [FFullPath, SR.Name])); Dir.FDirName := SR.Name; // An dieser Stelle müssen wir prüfen, ob das Verzeichnis Unterverzeichnisse besitzt // Dies wird benötigt, damit das "+" Symbol vor der Node angezeigt wird // Self.HasSubDirectories := CheckHasSubDirectories; Self.SubDirectories.Add(Dir); SHGetFileInfo(PChar(FFullPath + SR.Name), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON); Self.iIconIndex := Info.iIcon; end; until (FindNext(SR) <> 0); finally FindClose(SR); FAlreadyLoaded := True; end; end; |
AW: Application.CreateForm in einem Thread
Liste der Anhänge anzeigen (Anzahl: 1)
Allgemein zum VST:
Ich kann nur dazu raten das ganze generisch anzugehen und die Pointerspielerei nicht überall selbst zu machen...
Delphi-Quellcode:
Und dann in der Anwendung:
TBaseVirtualTreeHelper = class helper for TBaseVirtualTree
public function Get<T: class>(Node: PVirtualNode): T; end; { TBaseVirtualTreeHelper } function TBaseVirtualTreeHelper.Get<T>(Node: PVirtualNode): T; var ResultData: Pointer; begin ResultData := GetNodeData(Node); if Assigned(ResultData) and (TObject(ResultData^) is T) then Result := T(ResultData^) else Result := nil; end;
Delphi-Quellcode:
Ein weiterer großer Vorteil ist, dass du im Debugger sofort den Inhalt sehen kannst ohne aufzuklappen:
procedure TfrmDirectoryBrowser.vstDirectoryBrowserExpanding(Sender: TBaseVirtualTree; Node: PVirtualNode;
var Allowed: Boolean); var NodeData: TDirectory; begin Allowed := True; NodeData := Sender.Get<TDirectory>(Node); NodeData.LoadSubDirectories; // ggf. auf Assigned prüfen end; Anhang 47307 |
AW: Application.CreateForm in einem Thread
Zitat:
ich habe mir deinen Code zwar jetzt nicht eingebaut, aber du solltest beim OnGetImageIndex() Event folgendes beachten: Prüfe immer den ImageKind der übergeben wird. Es gibt insgesamt 4 (?) Typen. (Habe den Source gerade nicht vorliegen, daher aus dem Kopf)
Delphi-Quellcode:
In der Regel sind ikNormal und ikSelected die beiden meist benötigten Typen. Deshalb solltest du in dein OnGetImageIndex() Event die folgende Abfrage mit aufnehmen. Eventuell ist dadurch dein Problem schon behoben. Wenn nicht, dann solltest du dir die Images in der ImageList eventuell mal alle in einer PaintBox nebeneinander malen und sie dir anschauen.
ikNormal, // Wird angezeigt wenn die Node keinen speziellen Zustand hat
ikSelected, // Wird angezeigt wenn die Node ausgewählt ist (Sei es durch FocusedNode oder das die Node in einer Selection enthalten ist) ikState, // Habe ich bisher nie verwendet. Gibt aber wohl einen speziellen Status der Node an den man wohl wieder abfragen kann (bspw. wird gerade editiert oder so) (genauere Infos im SourceCode des VST) ikOverlay // Das Image, dass nochmal über das eigentliche Image drübergepinselt werden soll (auch hier genauere Infos im SourceCode des VST)
Delphi-Quellcode:
@Jaenicke: Ja kann man so machen. ;)
procedure TfrmDirectoryBrowser.vstDirectoryBrowserGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
var NodeData: PDirectory; Info: TSHFileInfo; begin if (Kind in [ikNormal, ikSelected]) then begin // Die Zeile hinzufügen (es sei denn du wolltest die speziellen Typen behandeln) NodeData := Sender.GetNodeData(Node); ImageIndex := NodeData^.iIconIndex; end; end; Ich konnte mich allerdings bisher nicht an die Umstellung auf Generics in Bezug auf den VST gewöhnen. Überall anders im Programm wird massiv mit Generics gearbeitet. Die Einführung kam ja irgendwann mit Version 6.X. Ich bin dabei seit den frühereren 4.X Versionen als er noch von Mike Lischke programmiert wurde. Und da war das alles noch ganz anders :) |
AW: Application.CreateForm in einem Thread
Zitat:
|
AW: Application.CreateForm in einem Thread
Zitat:
Hier ein Beispiel:
Delphi-Quellcode:
procedure TScreenControlsForm.vstScreenComponentsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType; var CellText: string); var Info: IScreenComponentInfo; begin Info := Node.GetData<IScreenComponentInfo>; if Assigned(Info) then begin CellText := Info.Text; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz