Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Findclose im Thread (https://www.delphipraxis.net/192284-findclose-im-thread.html)

Hobbycoder 5. Apr 2017 14:44

Findclose im Thread
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,

in meinem Projekt durchsuche ich festgelegte Verzeichnisse regelmäßig nach dem Vorkommen verschiedener Dateien. Diese erfolgt pro User so ca. 50-100 mal und wird im Hintergrund mittels eines Threads erledigt.
Innerhalb des Thread läuft das mittels FindFirst...FindNext, FindClose ab.

Wenn ich jetzt am Server mir mal unter "Geöffnete Dateien verwalten..." nachschaue, sind hundert von Einträgen vorhanden, die alle jeweils auf das Verzeichnis verweisen, welches recursiv durchsucht wurde (die Unterverzeichnisse allerdings nicht). Alle natürlich nur zum lesen mit 0 sperren.

Ich hatte eigentlich gedacht ein Findclose reicht aus. Es treten auch keine Fehler auf, aber mich stört dieser Umstand schon.
Auch glaube ich im Thread so keinen Fehler gemacht zu haben.

Wär schön, wenn ihr euch das mal anschauen könntet.

Danke Hobbycoder

himitsu 5. Apr 2017 16:01

AW: Findclose im Thread
 
Sicher, dass die Threads durchlaufen und nicht abstürzen?
Delphi fängt Exceptions in TThreads ab (da Windows sonst das ganze Programm hart abschießt), allerdings werden Exceptions im Thread nicht angezeigt, so wie es z.B. die VCL tut.

Entweder per Try-Except im Thread.Execute
oder im Thread.OnTerminate das
Delphi-Quellcode:
(Thread.FatalException as Exception)
prüfen und anzeigen/loggen.




Gut, abgesehn von fehlenden Ressourcen-Schutzblöcken (Try Finally) fällt auf die Schnelle nichts Schlimmes auf.

Da das in den Unterverzeichnisse nicht auftritt, würde ich einen Fehler in TThreadSearchDocuments.FindFileInPath eher ausschließen,
denn wenn da der Fehler wäre, dann doch in allen Ebenen? Die Funktion ist ja in sich geschlossen und ruft sich selber rekursiv aufruft.

Tipps:
Delphi-Quellcode:
if (Pos(lowercase(FName),lowercase(filename))>0)

if StartsText(FName, filename)
Und ein Verziechnis mit weiteren Attributen ist für dich kein Verzeichnis? (Bit-Maske)
Delphi-Quellcode:
if (sr.Attr = faDirectory)

if (sr.Attr and faDirectory <> 0)


Warum ist da eigentlich mehrfach fast der selbe Code drin (pro TrTyp) und das ganze auch noch doppelt (FAddDirectories) ?

Delphi-Quellcode:
procedure TThreadSearchDocuments.FindFileInPath(Path: string);
var
  sr: TSearchRec;
  filename: string;
begin
  if Self.Terminated then
    Exit;
  if FindFirst(path+'*.*', faAnyFile, sr)=0 then
    try
      repeat
        if (sr.Name='.') or (sr.Name='..') then
          Continue;
        Inc(TCount);
        DoOnDokumentCount(TCount);
        filename:=StringReplace(sr.Name, ' ', '', [rfReplaceAll]);
        if (sr.Attr and faDirectory = 0) or FAddDirectories then begin
          if .... (FName<>'') .. and StartsText(FName, .. filename) then TrTyp:='Name'
          else if (FKZ<>'') .... and StartsText(FKZ, .... filename) then TrTyp:='KZ'
          else if (FVIN<>'') ... and StartsText(FVIN, ... filename) then TrTyp:='VIN'
          else if (FDebitor<>'') and StartsText(FDebitor, filename) then TrTyp:='KdNr'
          else TrTyp:='';
          if TrTyp<>'' then begin
            TrName:=ExtractFileName(sr.Name); // steht hier nicht eh nur der Filename drin?
            TrPath:=Path;
            TrDatum:=FileTimeToDateTime(sr.FindData.ftLastWriteTime);
            TrGroesse:=sr.Size;
            DoOnFoundDokument(TrName, TrTyp, TrPath, TrDatum, TrGroesse);
          end;
        end;
        if FAddDirectories then
          FindFileInPath(path+sr.Name+'\');
      until Self.Terminated or (FindNext(sr)<>0);
    finally
      FindClose(sr);
    end;
end;
Ist nicht ganz eindeutig, das rumge-pos-se ... Wirklich Delphi-Referenz durchsuchenStartsText oder doch eher Delphi-Referenz durchsuchenSameText?
Für SameText, oder eher MatchText, da ja Mehreres:
Delphi-Quellcode:
//const cTrTyp: array[0..3] of string = ('Name', 'KZ', 'VIN', 'KdNr');
if (sr.Attr and faDirectory = 0) or FAddDirectories then begin
  if MatchText(filename, [FName, FKZ, FVIN, FDebitor]) then begin
    TrName:=ExtractFileName(sr.Name); // steht hier nicht eh nur der Filename drin?
    {case IndexText(filename, [FName, FKZ, FVIN, FDebitor]) of
      0: TrTyp:='Name';
      1: TrTyp:='KZ';
      2: TrTyp:='VIN';
      3: TrTyp:='KdNr';
      else TrTyp:=''; // im ELSE oder vor dem REPEAT initialisiert, damit der Compiler nicht meckert
    end;}
    TrTyp:=cTrTyp[IndexText(filename, [FName, FKZ, FVIN, FDebitor])];
    TrPath:=Path;
    TrDatum:=FileTimeToDateTime(sr.FindData.ftLastWriteTime);
    TrGroesse:=sr.Size;
    DoOnFoundDokument(TrName, TrTyp, TrPath, TrDatum, TrGroesse);
  end;
end;
StartsStr StartsText SameStr SameText MatchStr MatchText ... siehe Delphi-Referenz durchsuchenStrUtils



Testhalber mal ein
Delphi-Quellcode:
Exit;
an den Anfang von TThreadSearchDocuments.FindFileInPath und schauen, ob die Verzeichnisse immernoch offen sind.
Dann ist es definitiv wo anders.

Hobbycoder 5. Apr 2017 18:49

AW: Findclose im Thread
 
Danke für deine Mühe.

Try...finally....ja, natürlich.
Muss natürlich rein. Ist mir mal so überhaupt nicht aufgefallen. Asche auf mein Haupt.

Für den Rest hast du natürlich mal wieder ;-) klare Worte gefunden. Zugegebenermaßen war das reine Faulheit. Aus einer alten Procedure übernommen, mal eben mit copy&paste zusammengeklatscht.
Geht natürlich auch schöner. Ich werde das mal nach deinen Kommentaren überarbeiten und dann mal schauen, ob dann alles geschlossen wird bzw. wann welche Exception kommt (loggen).

Danke dir.

Gruß Hobbycoder


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:42 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