Pagina1 van 1
Forum

Welkom bij de Tweaking4All gemeenschapsforums!
Voor je gaat deelnemen, bekijk de Forum Regels!

Specifieke onderwerpen: Start het onderwerp met de naam van het programma of systeem.
Bijvoorbeeld “MacOS X – Jouw vraag“, of bijvoorbeeld “MS Word – Jouw Tip of Truc“.

Merk op: Omschakelen naar een andere taal zal niet werken als je een post aan het lezen bent aangezien er waarschijnlijk geen vertaling beschikbaar is.



Deel:
Meldingen
Alles wissen

[Opgelost] Lazarus - FindAllFiles onderbreken voor voortgang indicatie

1 Berichten
1 Gebruikers
0 Reactions
2,097 Bekeken
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
Topic starter  

Lazarus Pascal heeft een handige functie, "FindAllFiles", welke alle files en directories can vinden binnen een gegeven pad, met gegeven criteria, en geeft het antwoord terug als een nette TStringList.

Dit werkt erg goed, en snel, maar heeft een nadeel: het vreet resources op dusdanige manier dat jouw programma stil lijkt te zijn staan of lijkt te zijn vastgeslagen. Erg lastig voor de gebruikerservaring want de gebruiker weet niet of het nu nog bezig is, of dat het foute boel is, dus willen we graag een indicatie dat het e.e.a. nog draait.

Het liefste zouden we tussendoor een Application.ProcessMessages willen doen, maar dat gaat niet,... tenzij we een truc gebruiken die ik in het Lazarus Forum vond, van een gebruiker met de naam Molly.

Het eerste wat ik me moest realiseren is dat FindAllFiles op 2 manieren gebruikt kan worden: of je krijgt een TStringList als antwoord terug, of je geeft een bestaande TSTringList aan de functie door die dan de inhoud daarvan veranderd - en dat laatste biedt de oplossing.

Als voorbeeld heb ik op mijn Form een TLabel gebruikt die aangeeft hoeveel files er gelezen zijn, en een TButton om het zoeken te starten.
Dus we hebben een TLabel met de naam Label1, en een TButton met de naam Button1.

Vervolgens moeten we in onze code een TStringList, waaraan we een "OnChange" kunnen hangen welke dan weer Application.ProcessMessages kan aanroepen.

In code:

De handler voor het OnChange event:

procedure TForm1.FindAllFilesInterrupt(Sender: TObject);
Const UpdateFrequency = 10;
begin
  if (TStringList(Sender).Count mod UpdateFrequency = 0) then // for every 10th file
    begin
      Label1.Caption:='File count: ('+IntTostr(TStringList(Sender).Count)+')';
      application.ProcessMessages;
    end;
end;

Dit zal Label1 steeds per 10 gevonden files updaten. Je kunt voor UpdateFrequency een lagere waarde gebruiken, maar hoe lager deze waarde, hoe meer refreshes en dus hoe langzamer het geheel loopt (afhankelijk van jouw computer natuurlijk).

Vervolgens moeten we de dus een TStringList maken, de handler er aan hangen en FindAllFiles op de juiste manier aanroepen:

procedure TForm1.Button1Click(Sender: TObject);
var AllFiles : TStringList;
...
begin
   ...
  AllFiles := TStringList.Create;
  AllFiles.OnChange:=@FindAllFilesInterrupt;
  FileUtil.FindAllFiles(AllFiles,'/Path/we/want/to/scan','*.*',true);
  AllFiles.OnChange:=nil;  
  ...
end;

Als FindAllFiles klaar is, verwijder ik de handler weer - voor het geval we later met de TStringList dingen gaan uithalen.


   
BeantwoordenCiteren
Deel: