Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Dateien kopieren wird langsam. (https://www.delphipraxis.net/157118-dateien-kopieren-wird-langsam.html)

k4rstn 30. Dez 2010 13:34

Dateien kopieren wird langsam.
 
Hallo
Ich schreib zur zeit ein programm was viele datein kopieren sol...
es funzt auch schon recht gut, jedoch wird es nach ner weile recht langsam.
in der funktion "lesedatum" hatte ich zunächst FreeandNil(ImgData) vergessen, wodurch sich der genutzte RAM aufgebläht hat. Doch auch dadurch läuft das prog nicht mit konstanter geschwindigkeit.
hat jmd ne ahnung warum es gegen ende immer langsamer wird?

hier der code

Delphi-Quellcode:
function LeseDatum(datei:string):string;
var ImgData: TImgData;
begin
  ImgData := TImgData.Create;
  DexifDecode := true;
  ImgData.TraceLevel := 1;
       if ImgData.ProcessFile(datei) then
          if ImgData.HasExif then
            LeseDatum := ImgData.ExifObj.DateTime
          else
            lesedatum := ''
       else
       lesedatum :='';
  FreeAndNil(ImgData);
end;

function TForm1.trennedatum(datum:string) : TStrArray;
begin
trennedatum[0] := Copy(datum, 1, 4);
trennedatum[1] := Copy(datum, 6, 2);
trennedatum[2] := Copy(datum, 9, 2);
trennedatum[3] := Copy(datum, 12, 2);
trennedatum[4] := Copy(datum, 15, 2);
trennedatum[5] := Copy(datum, 18, 2);
end;

procedure TForm1.kopierebilder;
var
i : integer;
jahr,mon,tag : string;
n_jahr,n_mon,n_tag : string;
 fileSource, fileDest: string;
begin
Progressbar1.Max:=Liste.Count-1;
ListBox1.Clear;
  for i:=0 to Liste.Count-1 do
  begin
  Label1.Caption := inttostr(Liste.Count) + ' / ' + inttostr(Liste.Count) + ' Bilder kopiert.';
  ListBox1.Items.Add(Liste[i]);
  Progressbar1.Position :=i;
    if LeseDatum(Liste[i]) <> '' then
    begin
    jahr := trennedatum(LeseDatum(Liste[i]))[0];
    mon := trennedatum(LeseDatum(Liste[i]))[1];
    tag := trennedatum(LeseDatum(Liste[i]))[2];

    n_jahr := Ziel + '\' + jahr;
    n_mon  := Ziel + '\' + jahr + '\' + jahr + '_' + mon;
    n_tag  := Ziel + '\' + jahr + '\' + jahr + '_' + mon + '\' + jahr + '_' + mon + '_' + tag + '-';
    {$IOChecks off}
    if not(DirectoryExists(n_jahr)) then
      mkdir(n_jahr);
    if not(DirectoryExists(n_mon)) then
      mkdir(n_mon);
    if not(DirectoryExists(n_tag)) then
      mkdir(n_tag);
    {$IOChecks on}

    fileSource := Liste[i];
    fileDest := n_tag + '\' + ExtractFileName(Liste[i]);
    end
    else
    begin
      if not(DirectoryExists(Ziel + '\zeitlos')) then
        mkdir(Ziel + '\zeitlos');
    fileSource := Liste[i];
    filedest := Ziel + '\zeitlos' + '\' + ExtractFileName(Liste[i]);
    end;
    //ListBox1.Items.Add(filesource);
    //ListBox1.Items.Add(filedest);
    CopyFile(PChar(fileSource), PChar(fileDest), true);
    SendMessage(ListBox1.Handle, LB_SETTOPINDEX, ListBox1.Items.Count-1, 0);
  end;
  Progressbar1.Position :=0;
end;

himitsu 30. Dez 2010 13:39

AW: Dateien kopieren wird langsam.
 
Dateien werden erst in die schnelle WindowsFileCache geschrieben und landen danach erst auf der Festplatte.
Wenn man nun viele/große Dateien in diese WFC reinläd und Windows nicht schnellgenug diese auf die Fesplatte abspeichern kann, dann ist die WFC irgendwann voll und man kann nicht mehr mit voller Geschwindigkeit Neues dort reinladen, da ja erstmal was Altes raus muß.

OK, Speicherlecks verbrauchen auch Speicher und verringern somit ebenfalls die Größe/Effektivität der WFC.



Und je voller Listen sind, um so länger dauert es, wenn man darin was sucht oder verändert, vorallem sowas wie eine TListBox wird extrem langsam, je mehr darin steht.

sx2008 30. Dez 2010 14:52

AW: Dateien kopieren wird langsam.
 
Ich greife hier mal folg. Abschnitt raus:
Delphi-Quellcode:
if LeseDatum(Liste[i]) <> '' then
begin
  jahr := trennedatum(LeseDatum(Liste[i]))[0];
  mon := trennedatum(LeseDatum(Liste[i]))[1];
  tag := trennedatum(LeseDatum(Liste[i]))[2];
Das ist eine grosse Verschwendung, denn die Funktion LeseDatum() wird gleich 4 Mal aufgerufen!!
Warum verwendest du nicht einfach eine lokale (string-)Variable um das Ergebnis von LeseDatum() zwischenzuspeichern?

k4rstn 31. Dez 2010 12:30

AW: Dateien kopieren wird langsam.
 
wow danke sx2008 ...
das hat das proggie jetz schonma enorm beschleunigt, dass ich das nich selbst gesehn hab :-)
thx

k4rstn 31. Dez 2010 13:33

AW: Dateien kopieren wird langsam.
 
aber direkt mal ne andere frage, damit ich keinen neuen thread anfangen muss... das kopieren von vielen datein dauert ja nun ein wenig... wie stellt man es denn an, dass das formular während der for schleife bedienbar bleibt? bzw. habe ich ein label drin, auf dem stehen sollte 45 / 10456 Bilder kopiert. Jedoch erscheint das erst am Ende mit 10456 / 10456 Bilder kopiert.

edit: sehs grad im qt steht ja
Code:
Label1.Caption := inttostr(Liste.Count) + ' / ' + inttostr(Liste.Count) + ' Bilder kopiert.';
aber selbst wenn ich
Code:
Label1.Caption := inttostr(i) + ' / ' + inttostr(Liste.Count) + ' Bilder kopiert.';
schreibe gehts nich ..

Bernerbaer 31. Dez 2010 15:12

AW: Dateien kopieren wird langsam.
 
Zitat:

Zitat von k4rstn (Beitrag 1071432)
...
Code:
Label1.Caption := inttostr(i) + ' / ' + inttostr(Liste.Count) + ' Bilder kopiert.';
schreibe gehts nich ..

einfache Lösung:
Code:
Label1.Caption := inttostr(i) + ' / ' + inttostr(Liste.Count) + ' Bilder kopiert.';
application.processmessages;
komplexere Lösung:
Auslagerung des Kopiervorgangs in einen separaten Thread

himitsu 31. Dez 2010 15:49

AW: Dateien kopieren wird langsam.
 
Delphi-Referenz durchsuchenFormat kennt ihr aber?
Delphi-Quellcode:
Label1.Caption := Format('%d / %d Bilder kopiert.', [i, Liste.Count]);
Application.ProcessMessages;
Ja, man kann es über Delphi-Referenz durchsuchenProcessMessages lösen,
wobei sowas aber auch sehr nach der Verwendung eines Threads schreit.

sx2008 31. Dez 2010 20:13

AW: Dateien kopieren wird langsam.
 
Zitat:

Zitat von himitsu (Beitrag 1071493)
wobei sowas aber auch sehr nach der Verwendung eines Threads schreit.

Na ja, die Frage ist doch: kann das Programm während des Kopierens dem Benutzer irgendeine zusätzliche Dienstleistung bereitstellen?
Häufig ist es aber so, dass der Benutzer auf den Abschluss der Operation (hier: kopieren der Dateien) warten muss, bevor er sinnvoll weiterarbeiten kann.
Leider hat Delphi auch keine Multithreading-Gene in Objekt-Pascal selbst mitbekommen, so dass echtes Multithreading immer viel aufwändiger als das primitive Application.ProccessMessages ist.
Vom Aufwand/Nutzen Verhältnis her gesehen, würde ich hier keinen Thread benützen.
Rein technisch gesehen wäre es aber zumindest interessant, denn Multithreading ist einer der Megatrends der nächsten Jahre.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz