Registriert: Mo Jan 31, 2005 11:02 Beiträge: 432 Wohnort: Rheinlandpfalz
Ich weiß, dass ich das hier irgendwann schon mal ähnlich gelesen habe... aber ich find's nicht.
Naja, mein Problem ist, dass ich ein Array von Klassen habe, aus dem ich einen Eintrag in der Mitte löschen will.
Die anderen Klassen dahinter sollen eins nachrücken, und dann lösche ich den letzten Eintrag.
Eigentlich sind Klassen ja nur Pointer, also könnte man sie ja einfach zuweisen in dem man aufruft:
Code:
Klasse[0]:= Klasse[1];
Das geht aber nicht, wie ich schon fast vermutet hatte...
Dazu kommt noch, dass meine Klassen auch wieder ein Klasse von TStream beinhalten. Das macht vllt noch zusätzlich Probleme.
Dieser TStream ist zur Laufzeit ein MemoryStream, der eine nicht unbeträchtliche Menge an Daten mit sich schleift. Sagen wir mal um die 100Kb ist aber variabel. D.h. Ich habe in meinem zum Beispiel 30 Elemente à 100Kb macht ungefähr 3Mb Daten, die ich im Ram verschieben müsste...
Als weiteres Übel hab ich ein dynamisches Array in jeder Klasse. Das wirkt sich auch nicht besonders gut auf den Tausch aus, schätze ich.
Wisst Ihr, wie ich sowas anstelle, ohne alle Daten kopieren zu müssen?!
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Was geht denn daran nicht?
Denn normal sind Klasseninstanzen nur Pointer und die kannst du problemlos in Arrays hin und herschieben. Was da hinten dran hängt spielt absolut nicht die geringste Rolle. Du musst bei Klasseninstanzen nur die Pointer kopieren. Das kannst du eigentlich sogar mit einem Move erledigen.
Also sag mal bitte was daran nicht geht und im zweifel etwas mehr code.
Redest du von Klassen oder von Instanzen einer klasse? Normal solltest du beide ganz normal in einem array verwalten könne. Ich empfehle allerdings eher eineTList, da bei der einfügen, löschen etc leichter geht. (afaik ist die intern auch ein array)
Registriert: Mo Jan 31, 2005 11:02 Beiträge: 432 Wohnort: Rheinlandpfalz
The Winner hat geschrieben:
Redest du von Klassen oder von Instanzen einer klasse?
Ich meine schon Instanzen.
Also nach längerem probieren ich hab es jetzt hinbekommen.
Es lag irgendwie an meinem TTreeView, das da nicht mitmachen wollte.
So hab ich es gemacht:
Code:
Function TPakFile.DeleteFile(Id:Word):Boolean;
Var
i :Integer;
Begin
Result :=(Id < FSubFileCount);
If(not Result)then
Exit;
FSubFile[Id].Free;
For i := Id toHigh(FSubFile)-1do
FSubFile[i]:= FSubFile[i+1];
SetLength(FSubFile,High(FSubFile));
Dec(FSubFileCount);
End;
Also ich befreie erstmal die Daten vom zu löschenden Index, dann rück ich alle eins nach, und verkürze das Array um eins.
Aber es ist kaum ein Unterschied zu meiner vorigen Methode zu bemerken. Vorher hab ich alle Daten einzeln kopiert. Jetzt verschiebe ich ja nur Pointer.
Dennoch hängt das Programm ca. 5 ganze Sekunden bis es wieder reagiert. Dabei habe ich bloß ein Array mit 113 Werten und damit insgesamt 3,5 Mb im Speicher belegt...
Also entweder kopiert er intern doch, oder ich hab was falsch gemacht...
bei 100 Objekten und einem billigen destruktor dürfte die funktion nicht teuer sein. Geh mal mit dem debugger drüber und schau wo genau er so lange hängt, oder ob High(FSubFile) größer ist als gedacht.
Registriert: Mo Jan 31, 2005 11:02 Beiträge: 432 Wohnort: Rheinlandpfalz
Ok, ich konnte das Problem jetzt etwas eingrenzen...
Es liegt nicht an der Methode des Löschens. Ich hab nämlich zum Test mal alle VCL Sachen rausgeschmissen, und siehe da: Es läuft wunderbar!
Also muss es an meinem TreeView liegen... Jetzt hab ich sogar manchmal Probleme (5 Sekunden+), wenn ich nur Dateien hinzufügen will. Irgendwie ist das alles sehr seltsam...
Aber ich hoffe ich komme dem ganzen noch auf die Schliche.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Fügst du die Objekte denn in die Treeview ein? Und wieviele sind es? Ab einer gewissen Anzahl von Einträgen wird die VCL-Treeview verdammt langsam. Dann solltest du auf VirtualTreeView umsteigen, was deutlich schneller (und mächtiger) ist.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Mo Jan 31, 2005 11:02 Beiträge: 432 Wohnort: Rheinlandpfalz
Es reichen schon 100 Elemente.
Die TreeView benutze ich eigentlich nur zur Visualisierung meiner Daten.
Im Prinzip hänge ich nämlich alles an mein Klassen-Array an, und wenn ich etwas löschen will, dann lösche ich es eben aus diesem Array.
Nachdem das getan ist, lösche ich die TreeView komplett (TreeView.Clear) und lade sie neu, dabei gehe ich mein Array von Klassen durch und greife auf einen privaten String zu, welchen ich dann an die TreeView hänge.
Ich weiß, dass das nicht besonders performant ist, jedoch hat es seine Gründe...
Außerdem kann das eigentlich nicht so lange dauern... Denn wenn ich das letzte Item in der TreeView anwähle und die oben beschriebene Aktion durchführe, geht es wunderbar schnell, jedoch wenn ich eines der oberen Einträge in der TreeView anwähle, und die Aktion durchführe, dann hängt es.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also 100 Elemente sind keine Menge. Du kannst / solltest beim Zugriff auf die Einträge aktualisieren unterbinden. Das geht mit Items.BeginUpdate und Items.EndUpdate. Darin sollte das Clear und Hinzufügen der Einträge enthalten sein.
Allerdings muss ich gestehen. Ich habe hab schon "ein paar" mal Dinge damit gemacht und ich vermute eher, dass es irgendetwas im Zusammenspiel damit zu tun hat. Ungünstige Aktionen beim Befüllen oder so was. Allerdings können wir das mangels Infos nicht sagen.
Ich hatte es schon mal, dass ein Code von mir knapp das Zehnfache an Zeit benötigt hatte nur weil er an einer Grenze des Speichermanagers von Delphi lag. Ich habe innerhalb immer wieder ein String erstellt und gelöscht. Dadurch musste Delphi wohl mehr machen. Also ich noch einen String mehr hatte lief es. Allerings glaube ich nicht, dass es so etwas ist. Aber gibt auch Fälle in denen auch nur eine blöde Konstellation ausreicht. Die sind aber eher seltener.
Registriert: Mo Jan 31, 2005 11:02 Beiträge: 432 Wohnort: Rheinlandpfalz
Lossy hat geschrieben:
Du kannst / solltest beim Zugriff auf die Einträge aktualisieren unterbinden. Das geht mit Items.BeginUpdate und Items.EndUpdate. Darin sollte das Clear und Hinzufügen der Einträge enthalten sein.
Danke, das werde ich mal probieren.
Eigentlich sollte es ja nicht hängen, aber was will man machen?! Ich werde heute noch etwas rumspielen, vllt bekomme ich das Problem ja noch gelöst. Ansonsten muss ich halt Clear irgendwie vermeiden.
Lossy hat geschrieben:
Ungünstige Aktionen beim Befüllen oder so was.
Mal schauen, was da alles involviert ist, obwohl da eigentlich nicht viel passiert...
Registriert: Mo Jan 31, 2005 11:02 Beiträge: 432 Wohnort: Rheinlandpfalz
Hab den Übeltäter jetzt entlarvt. Es lag an der TreeView.OnChange Procedure. Darin hab ich etwas gemacht, was einmal ausgeführt sehr schnell geht,
Wenn es hundertmal ausgeführt wird aber sehr lange dauert. Irgendwie ruft die TreeView.Items.Add Funktion die OnChange auf, aber unterschiedlich oft, je nach dem, was für einen Index ich gerade selektiert habe... warum auch immer.
Egal, ein bisschen Code zum abfangen dieses Problems in der OnChange und schon läuft es.
Danke für die Hilfe.
Mitglieder in diesem Forum: 0 Mitglieder und 8 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.