Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mi 30.05.07 10:51 
Ich hab da grade ein kleines konzeptionelles Problem. :gruebel:

Ich habe in meinem Programm eine ganze Menge von Dateien, die ich verwalten möchte. Aus bestimmten Gründen brauche ich zur Laufzeit 2 Listen (ListeA und ListeB, TObjectList), die nach unterschiedlichen Kriterien sortiert sind, in denen jeweils alle Dateien enthalten sind.
Jetzt möchte ich gerne diese Listen aktuell halten. D.h. bei Programmstart soll überprüft werden, ob alle Dateien noch vorhanden sind und/oder ob neue dazugekommen sind. Wenn ich das direkt auf ListeA und ListeB mache, dann ist der sehr langsam (klar, warum oder?). Daher brauche ich dafür eine weitere Liste ListeP, die nach Pfad sortiert ist, in der ich dann eine Binärsuche starten kann. Das Löschen und/oder einfügen passiert also zunächst nur in der ListeP, A und B bleiben erstmal unangetastet. Damit die GUI nicht einfriert, passiert das in einem Thread (bzw. soll da passieren). Der User kann während der Suche nach neuen Dateien weiter A und B fürs Blättern in der Dateiliste benutzen.

Jetzt bleibt das Problem, am Ende ListeA und B auf den neuesten Stand zu bringen. Das Sortieren alleine benötigt auch ein paar Sekunden (je nach Umfang der Liste so ca. 1-5sek), in der die GUI dann eingefroren wäre. Ich würde das jetzt auch in einen Thread auslagern, indem ich aus der neuen ListeP zwei Listen ListeAneu und ListeBneu generiere, diese in einem Thread sortiere und anschließend mit den alten Listen vertausche. Dann würde der User fast nichts von dem Update-Prozess bemerken (außer dass die Platte rattert).

Ein weiteres Problem ist das Entfernen von nicht mehr vorhandenen Dateien. Hier würde ich die Dateien in einem Thread aus ListeP entfernen. Wenn ich nun aber das Objekt "Datei", was in der ListeP hängt, da schon freigebe, kann es in ListeA und B krachen, wenn auf dieses Objekt zugegriffen wird. Daher würde ich die Lösch-Dateien zunächst in einer ListeDel sammeln, bei Ende des Threads ListeA und B aktualisieren, und anschließend die Objekte in ListeDel freigeben.

Und zuletzt: Der User kann während des Update-Prozesses natürlich auch auf den Gedanken kommen, weitere Ordner und Dateien in die Liste mitaufnehmen zu wollen. Hier würde mir nur einfallen, das in der Zeit (auch während die Dateisuche läuft!) weiter blockiert zu lassen - sonst komme ich ja komplett durcheinander.

Jetzt meine Frage: Geht das auch einfacher? :gruebel:

_________________
We are, we were and will not be.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 31.05.07 11:00 
Der Ansatz mit der Liste ListeP ist schon mal gar nicht so schlecht. Anstatt allerdings Änderungen an ListeP vorzunehmen könnte man anhand der Liste die nötigen Änderungsoperationen für ListeA und ListeB generieren: Aufschreiben welche Objekte zu entfernen sind, und welche hinzuzufügen sind.

Dabei kann man folgende Sache ausnutzen:
1. Teilmengen (die zu löschenden oder einzufügenden Objekte) gehen recht einfach zu sortieren
2. Man brauch an diesen Teilmengen für den Abgleich mit ListeA und ListeB nichts verändern; lediglich vor der Übernahme der Änderungen die Sortierung nach dem jeweiligen Kriterium, um den Abgleich in linearer Zeit ausführen zu können.
3. Einzufügende Objekte können genauso wie die zu entfernenden Objekte relativ einfach einsortiert werden, sollten jedoch von hinten nach vorne übernommen werden.

Das Vorgehen wäre also:
1. Aufbau der ListeP sortiert nach Pfaden ...
2. Feststellen gelöschter Objekte
3. Feststellen hinzugefügter Objekte
4. Sortieren von ListePadded nach Kriterium für ListeA
5. Einfügen von ListePadded in ListeA
6. Umsortieren von ListPadded nach Kriterium für ListeB
7. Einfügen von ListePadded in ListeB
8. Wiederhole 4. bis 7. für ListePdeleted
9. Freigeben der Objekte in ListePdeleted

HTH.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 31.05.07 11:52 
Schön, dass hier wenigstens einer antwortet :lol:

Ja, so in etwa habe ich mir das auch vorgestellt. Neu ist jetzt der Gedanke, nur die neue Liste (also die neuen Objekte, bzw. die "toten") zu sortieren und diese Sortierung sowie die vorhandene Sortierung bei den alten Listen auszunutzen.
Das Einpflegen dieser Listen in die vorhandenen müsste aber trotzdem über eine Zwischen-Liste passieren. Wenn in eine 10.000 Dateien-Liste weitere 10.000 Dateien eingefügt werden sollen, dann dauert das recht lange, da ja TObjectlist eine Array-Struktur zugrundeliegt. Da müsste man beim Einfügen dann wie bei Merge-Sort arbeiten und hinterher die Listen vertauschen.
Aber: Einfacher wird das dadurch nicht - eher noch komplizierter. :tongue:

_________________
We are, we were and will not be.
azubi_20
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 593

WinXP SP2, Ubuntu 8.4
D7 Enterp., D2005 Prof., Java (Eclipse 3.4.0)
BeitragVerfasst: Do 31.05.07 13:35 
Also zum Problem, dass der User während des Update-Prozesses irgendetwas verändert, das den Prozess stört hätte ich folgende Vorschläge:
  • Das Programm überpüft beim Start auf Updates. Sind Updates nötig erscheint ein Fenster das den Fortschritt der Updates visualisiert. Erst danach wird die eigentliche GUI gezeigt, mit dem der User arbeitet.

oder falls es auch während des Benutzens des Programmes zu Updates kommen muss :
  • Es wird eine Meldung an den User ausgegeben, dass Updates vorliegen. Nach dessen Bestätigung werden die Referenzen auf Objekte, die in Benutzung sind, in einer temporören Liste gespeichert. Das Update wird durchgeführt, der Fortschritt wird in einem modalem Fenster visualisiert. Danach wird anhand der temporären Liste ein Abgleich gemacht und es wird versucht die Objekte wieder herzustellen. Entsprechende Meldungen an den User über entfernte oder geänderte Objekte, die in Benutzung waren geben dem User Informationen über die Update-Auswirkungen.


Und mit Application.ProcessMessages; sollte man dem Einfrieren der GUI entgegenwirken. :wink:

Ich hoffe ich hab das so richtig verstanden, was du vorhast.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 31.05.07 14:19 
user profile iconazubi_20 hat folgendes geschrieben:
Das Programm überpüft beim Start auf Updates. Sind Updates nötig erscheint ein Fenster das den Fortschritt der Updates visualisiert. Erst danach wird die eigentliche GUI gezeigt, mit dem der User arbeitet.
Genau das möchte ich vermeiden. Grund: Das Programm ist ein mp3-Player mit Medienbibliotek ;-). Wenn ich bei jedem Start warte, bis eine (in naher Zukunft für ganz Bekloppte) Terabyte-Platte nach neuen Dateien durchsucht wurde, dann dürfte das Programm kaum Anhänger finden :mrgreen:.
user profile iconazubi_20 hat folgendes geschrieben:
Und mit Application.ProcessMessages; sollte man dem Einfrieren der GUI entgegenwirken. :wink:
Joah, APM kenne ich schon, aber das hilft bei dem Problem herzlich wenig. Denn während die Suche nach neuen Dateien läuft, muss ich bisher die Nutzung der Medienbib sperren, da es sonst zu unschönen Effekten kommen kann. Das resultiert aus der nötigen Sortierung der ListenA und B, wovon ich bisher eine temporär nach Pfad sortiere, das Update durchführe, und dann zurücksortiere. Deswegen suche ich nach Möglichkeiten, diesen Prozess soweit wie möglich in den Hintergrund zu drängen, so dass a.) da ganze auch bei großen Datenmengen performant abläuft und b.) der User davon so gut wie nichts mitbekommt - außer evtl. eine Meldung in der Statusbar "So...Update fertig. Eben waren 10.000 Dateien in der Liste. Davon sind 5000 nicht mehr da, aber es gibt 20.000 neue. Viel Spaß bei 3 Monaten Musikgenuss."

Die einzige Einschränkung, die der User wahrscheinlich in Kauf nehmen wird müssen ist, dass er während der Suche nach neuen Dateien nicht selbst weitere Ordner einfügen kann - das wäre aber imho zu verschmerzen.

_________________
We are, we were and will not be.