![]() |
Luckie's DriveTools in einen Thread auslagern
Hi ihr,
mir brummt der Kopf. Ich versuche gerade, die ![]()
Delphi-Quellcode:
Ich habe die Unit auf die wichtigsten Teile gekürzt. Der Thread funktioniert auch soweit. Allerdings habe ich das Problem, dass das Fenster "ruckelt". Es springt beim Verschieben und reagiert sehr behäbig. Ich fürchte, irgendwo bin ich gestolpert, nur wo? Sieht jemand vielleicht von euch (Luckie? :) ), was ich da verbockt habe?
(*| Copyright (c) 2005 Michael Puff |*)
uses Windows, Messages; type TStringArray = array of string; const {...} type TFindFiles = class(TObject) private fThread: THandle; fThreadID: Cardinal; {...} procedure ThreadProc; {...} public {...} end; var FFTerminate: Boolean; {...} implementation function GlobalThreadProc(Ptr: Pointer): DWORD; begin TFindFiles(Ptr).ThreadProc(); end; constructor TFindFiles.Create(Handle: THandle; RootFolder: string; Mask: string; Recurse: Boolean; Progress: Boolean); begin fThread := BeginThread(nil, 0, @GlobalThreadProc, Self, CREATE_SUSPENDED, fThreadID); FHandle := Handle; FProgress := Progress; FFTerminate := False; if FProgress then Init; end; procedure TFindFiles.Init; begin FCntFolders := 0; FiFolder := 0; FLevel := 0; if FProgress then begin SendMessage(FHandle, FFM_INIT, 0, 0); CountFolders(FRootFolder, FRecurse); Sendmessage(FHandle, FFM_MAXFOLDERS, FCntFolders, 0); end; end; procedure TFindFiles.CountFolders(RootFolder: string; Recurse: Boolean); var hFindFile : THandle; wfd : TWin32FindData; begin {...} end; procedure TFindFiles.Find(Handle: THandle; RootFolder: string; Mask: string; Recurse: Boolean = True); var hFindFile : THandle; wfd : TWin32FindData; begin {...} end; procedure TFindFiles.ThreadProc; begin Find(FHandle, FRootFolder, FMask, FRecurse); SendMessage(FHandle, FFM_FINISH, 0, 0); end; procedure TFindFiles.FindFiles; begin ResumeThread(fThread); end; class procedure TFindFiles.Terminate; begin FFTerminate := True; EndThread(0); end; //Edit: Argh, beim Absenden kam mir einen Idee: In der "Find" - Funktion werden zwei Nachrichten abgesetzt. Einmal, wenn ein Ordner "gefunden" wurde, und einmal bei einer Datei. Auf die Nachricht der Datei reagiere ich, indem ich die ID3-Tags der Datei auslese und in eine SQLite-DB speicher. Das ist offensichtlich der Flaschenhals, denn kommentiere ich diesen Part aus, "ruckelts" nicht mehr. Ich fürchte, jetzt muss ich mir was anderes einfallen lassen... Das Schreiben in die DB muss noch in den Thread... Aiaiai... :gruebel: |
Re: Luckie's DriveTools in einen Thread auslagern
Du weist aber, dass du deine GlobalThreadProc nicht brauchst, sondern auch gleich deine Methode aufrufen kannst (in BeginThread übergeben).
|
Re: Luckie's DriveTools in einen Thread auslagern
Dachte ich mir auch, aber dann bekomme ich den Fehler
Zitat:
Delphi-Quellcode:
function ThreadProc(P: Pointer): DWORD;
|
Re: Luckie's DriveTools in einen Thread auslagern
Delphi-Quellcode:
Mach ich ständig so.
constructor TTest.Create;
var id:Cardinal; begin BeginThread(nil,0,@TTest.Thread,self,0,id); end; function TTest.Thread: Integer; begin end; Was machst du eigentlich mit dem EndThread da? |
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
Den Thread beim Zerstören des Objekts beenden. Nicht nötig? |
Re: Luckie's DriveTools in einen Thread auslagern
Nicht nötig. Einfach aus der Threadproc rausgehen. Und in deinem Fall verstehe ich den Sinn sowieso nicht.
|
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
|
Re: Luckie's DriveTools in einen Thread auslagern
ist der Prozess weg, sind auch die Threads und alle möglichen (nicht gemeinsamen) Handles und auch der zugehörige Arbeitsspeicher weg, aber dennoch kann man ja selber noch ordentlich aufräumen.
|
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
|
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
@himi: Mein Reden. :mrgreen: Danke. ;) |
Re: Luckie's DriveTools in einen Thread auslagern
Ich weiß, dieser Beitrag ist schon fuuurchtbaar lange her (übermorgen kann man sagen: Von letztem Jahr!) :mrgreen:
Aber ich bin an dem Thema wirklich interessiert. Deshalb hier zwei Fragen: 1. @Daniel G: Würdest du bitte die Früchte deiner Arbeit mit uns teilen? Also einen funktionierenden Code posten oder ein Demo als Anhang? 2. Ist in dem ![]() Guido. |
Re: Luckie's DriveTools in einen Thread auslagern
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Zitat:
![]() Der Code steht unter der MPL 1.1 |
Re: Luckie's DriveTools in einen Thread auslagern
Hallo Daniel G,
zunächst mal danke für die schnelle Antwort und das Hochladen der Datei! :-D Meine Antwort hat etwas länger gedauert, da ich mich mit deinem Code und dem SmallTune-Projekt beschäftigt habe. Ich habe den Code in dgstFindFiles.pas schonmal überflogen. Dabei ist mir aufgefallen, dass du eine interessante Art der Implementation der Suchroutinen geschrieben hast! Ich kenne den Ablauf, in dem in einer Schleife nach Ordnern und Unter-Ordnern, und dann rekursiv in einer zweiten Schleife nach Dateien gesucht wird, usw. In deinem Code wird das scheinbar "in einem Aufwisch" gemacht, wobei dann die Filterung per Maske auch auf eine eigene Art erledigt wird. Wie gesagt, hab den Code erst überflogen. Werd in mir noch näher anschauen! Ansonsten fehlten da ein paar units, die für diese hier benötigt werden. An der Stelle meinen Dank für den Hinweis mit ![]() Hast du vielleicht ein Aufruf-Beispiel oder ein kleines Demo, bei dem auch das OnProgress gezeigt wird? Würde mich sehr freuen! Denn ich tue mir im Moment ein wenig schwer damit, was wo in welchem Thread abgerufen wird, bzw. ankommt. Hast du (oder jemand anderes) schon den ![]() Guido. |
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
Dort wird doppelt gesucht - einmal zur initialisierung, worüber das Ende der ProgressBar bestimmt wird - und dann NOCHMAL für's Suchen außerdem wird jede Datei in diesem Label angezeigt, was enorm ausbremst Gerade daß man doppelt suchen muß, ist bei dieser Art des Fortschritts ein Problem. ![]() Dort kann man sich über den Callback anzeigen lassen, wo die Suche sich gerade befindet, worüber sich dann der User in etwa ausdenken kann, wie lange es eventuell noch dauert (darüber muß man sich zwar in etwa über seine Ordnerstrucktur im klaren sein, aber wer weiß denn nicht, was er auf seinem Rechner hat :angel2: ) Und sundance bastelt da auch gerade etwas ![]() |
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
![]() Eigentlich brauchst du als externe Abhängigkeit nur die Like-Funktion. Der relevante Teil, der den Code nutzt, findet sich hier:
Delphi-Quellcode:
Wobei TMaskArray einfach ein "Array of String" ist.
procedure TMediaClass.AddFolderToDatabase(FolderPath: String);
var Msk: TMaskArray; begin SetLength(Msk, 4); Msk[0] := '*.mp3'; Msk[1] := '*.ogg'; Msk[2] := '*.wma'; Msk[3] := '*.flac'; FF := TdgstFindFiles.Create(FolderPath, msk, true); FF.OnFilesDone := FindFilesDone; FF.OnProgress := FindfilesProgress; FF.StartSearch; end; OnFilesDone wird aufgerufen, wenn alle Dateien aufgelistet wurden, OnProgress bei jedem Dateifund. |
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
|
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
Sobald ich mal Zeit habe dieses zu ändern, wird es bei mir wieder ausgebaut, da es einfach nur nervt, wenn knapp 1,5 Minuten lang eine Initialisierung läuft. OK, hatte es dann so gemacht, daß nach 'ner halben Minute die Suche paralell mitläuft (dann braucht die initialisierung "nur" etwa 2 Minuen, aber insgesamt geht es schon schneller) In einem Testprojekt läuft es jetzt ohne vorherige Suche/Initialisierung und mit 'ner passend optimierteren Dateiliste/Dateiverwaltung und das insgesamt weit über 30% schneller. Gut, wenn genügend RAM frei ist, dann läuft der zweite Suchdurchlauf schneller, da dann noch alle Verzeichnisse in der WFC rumliegen. Wobei ich vielleicht erwähnen sollte, daß es sich hier um Laufwerke mit Datei-/Verzeichnisanzahlen im 5- bis 6-stelligen Bereich handelt, wo das doppelte Suchen schon sehr auffällt. (mit viel Zeit im Rücken würde ich das Ganze dann auch gerne mal auf ein direktes Auslesen der MFT umstellen) |
Re: Luckie's DriveTools in einen Thread auslagern
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Zitat:
Zitat:
Zitat:
![]() Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
![]() ![]() Zitat:
Ok, hier ist das "Weiter unten". Ich versuche meine Ansichten mal möglichst auf einen kurzen Nenner zu bringen: 1. Bei der Suche kann man rekursiv oder iterativ vorgehen. Was welche Vorteile hat, sei hier mal dahingestellt. 2. Nach Windows 98 werden die Tabellen, die bei einer von uns gemeinten Suche beim ersten Durchlauf gemacht werden, vom Betriebssystem gecacht. (Ob das bei Win 2000 so ist, nehme ich an, bei XP definitiv.) 3.Es spiel keine Rolle, ob man den ersten Durchlauf nun zum Initialisieren benutzt, um bei der ausführlichen Suche einen Progress anzuzeigen, oder direkt für eine Suche. Der erste Duchgang dauert halt länger. Das sind jetzt keine empierische Erkenntnisse, sondern einfach meine Ansicht. Die wird durch einen Test untermauert, von dem sich im Anhang ein Screenshot der Ergebnisse befindet. Edit: Die Ergebnisse sind gerundet. Der Test wurde nach eine Windows-Neustart durchgeführt. Nach dem ein Bereich (in diesem Fall ein Laufwerk) durchsucht wurde, dauert jede weitere Suche (insbesondere Initialisierung) nur ein Bruchteil der ersten Suche. Das bleibt so, bis zum nächsten Windows-Neustart. Guido. PS: Off-Topic: Guten Rutsch! :party: :cheer: :cheers: :party: Edit: Hinweis für gerundete Ergebnisse. |
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
Will man auf Biegen und Brechen einen Fortschritt mit "ungefährer" Endpunktanzeige, dann geht es nicht anders. *Meßwerte anguck* und sowas hab ich auch erwartet. Und genau deswegen laß ich zukünftig diese Art der "Initilisierung" weg und fang direkt mit der Suche an, denn das ist und bleibt das Schnellste. PS: da in der Realität soeine Suche zum Großteil nicht mehrfach kurz hintereinander gemacht wird und/oder beim weiteren Durchlauf (ein Durchlauf = Init+Suche oder nur Suche) die Ordnerstruktur vermutlich nicht mehr komplett im Cache (WFC = WindowsFileCache) liegt, kann man diesen Fall ignorieren und gleich davon Ausgehn, daß eine Initialisierung/Vorschausuche nicht von der WFC profitieren wird. Die reine Suche ist demnach langsamer, als die Initialisierungssuche. (weitere Verarbeitungen, wie z.B. Dateien in Listen einfügen, mal ignoriert) |
Re: Luckie's DriveTools in einen Thread auslagern
Im Regelfall reicht es ja auch einfach, eine Progressbar im Marquee-Stil anzubieten. Man beschleunigt so die eigentlich Suche; der User merkt aber dennoch, dass sich was tut.
|
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
Zitat:
Zitat:
Zitat:
Guido. |
Re: Luckie's DriveTools in einen Thread auslagern
Zitat:
Vorschausuche/Initialisierung + Suche ist insgesamt langsamer als nur eine Suche Zitat:
Allerdings ändere ich dann die gesamte Programmstrucktur, da die Verarbeitung der gefundenen Dateien auf den Gesamtprozess eine große Wirkung hat ... die Suche ist ja nicht der Einzige Bearbeitungsabschnitt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 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