Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi [Threads] Datei exklusiv öffnen (https://www.delphipraxis.net/30811-%5Bthreads%5D-datei-exklusiv-oeffnen.html)

sieppl 29. Sep 2004 16:49


[Threads] Datei exklusiv öffnen
 
Hallo,

mein Programm zeigt in einer ListView Thumbs von Bildern.
Bei mir laufen 2 Threads. Ein Thread wartet auf Änderungen in dem gerade betrachteten Ordner.
(FindFirstChangeNotification). Sobald es eine gibt, wird der 2. Thread aufgeweckt und rendert
falls vorhanden, neue Thumbs hinzu. Das Ganze läuft eigentlich ganz gut.
Problem:
Wenn ich mehrere Bilder (100) in den Ordner kopiere wird FindNextChangeNotification mehrere Male ausgelöst, nicht nur einmal, wenn der komplette Kopiervorgang abgeschlossen ist. Ist auch ganz schön, dass es zwischendurch aktualisiert wird.
Nun rennt der 2. Thread los findet alle Bilder die zu einem bestimmtem Zeitpunkt schon vorhanden sind und versucht die Bilder zu rendern. Jetzt gibt es sporadische 'File Open Error' da auch Windows noch kopiert und der Thread wahrscheinlich auf manche Files zugreift, während diese sich noch in einem schwebenden Zustand befinden. Die File-Zugriffe sind natürlich in einem try-error Konstrukt, dass heißt der Bug fällt nicht auf, wenn ich die Exe ausführe, da der Thread zum Schluss sowieso nochmal drüberrennt und alle nicht gerenderten Bilder erwischt.
Das ist aber nicht sauber. Habt Ihr Ideen? Ich suche so eine Art exklusiven Zugriff oder eine Prüfung ob die Datei schwebend ist oder nicht. Gerne auch API-Befehle, das Programm besteht zum größten Teil aus ihnen..

Grüße

Sebastian

shmia 29. Sep 2004 17:15

Re: [Threads] Datei exklusiv öffnen
 
Mit folgenden Funktionen kannst du prüfen, ob eine Datei im Zugriff von anderen Anwendungen ist:
Delphi-Quellcode:
function FileIsClosed(const filename:string):Boolean;
const
   FILE_SHARE_EXCLUSIVE = 0;
var
   hnd: THandle;
begin
   hnd := CreateFile(PChar(filename), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_EXCLUSIVE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

   result := hnd <> INVALID_HANDLE_VALUE;

   CloseHandle(hnd);
end;

function CheckIfFileExistsAndIsReadable(const AFileName: string): boolean;
begin
   Result := FileExists(AFileName) and FileIsClosed(AFileName);
end;
Ich würde aber trotzdem eine andere Vorgehensweise empfehlen:
bilde ein Liste der Dateien, für die ein Thumb erzeugt werden soll.
Die Liste wird abgearbeitet; bei Erfolg wird das Element aus der Liste gelöscht oder markiert,
bei Misserfolg eben nicht.
Nach Abarbeiten der Liste wird diese nochmals abgearbeitet, um die Misserfolge auszubügeln.

sieppl 29. Sep 2004 17:16

Re: [Threads] Datei exklusiv öffnen
 
Mit diesem Konstrukt fange ich viele Notifications erstmal ab und synchronisiere dann erst:
Delphi-Quellcode:
if WaitForSingleObject(FHandle, 500) = WAIT_OBJECT_0 then
      begin
        //catch mutliple notifications to enhance performance
        FindNextChangeNotification(FHandle);
        while WaitForSingleObject(FHandle, 500) = WAIT_OBJECT_0 do
          FindNextChangeNotification(FHandle);
        Synchronize(ExecuteOnChange);
      end;
Falls Ihr bessere Ideen habt, bitte posten!

Grüße

Sebastian

sieppl 29. Sep 2004 17:24

Re: [Threads] Datei exklusiv öffnen
 
Zitat:

Zitat von shmia
Mit folgenden Funktionen kannst du prüfen, ob eine Datei im Zugriff von anderen Anwendungen ist:
Delphi-Quellcode:
function FileIsClosed(const filename:string):Boolean;
const
   FILE_SHARE_EXCLUSIVE = 0;
var
   hnd: THandle;
begin
   hnd := CreateFile(PChar(filename), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_EXCLUSIVE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

   result := hnd <> INVALID_HANDLE_VALUE;

   CloseHandle(hnd);
end;

function CheckIfFileExistsAndIsReadable(const AFileName: string): boolean;
begin
   Result := FileExists(AFileName) and FileIsClosed(AFileName);
end;
Ich würde aber trotzdem eine andere Vorgehensweise empfehlen:
bilde ein Liste der Dateien, für die ein Thumb erzeugt werden soll.
Die Liste wird abgearbeitet; bei Erfolg wird das Element aus der Liste gelöscht oder markiert,
bei Misserfolg eben nicht.
Nach Abarbeiten der Liste wird diese nochmals abgearbeitet, um die Misserfolge auszubügeln.

Danke! :cyclops:
Den Code kann ich später noch gut gebrauchen. Bei mir war aber tatsächlich die große Anzahl von Notifications das Problem. Jetzt läuft alles viel performanter und die Zugriffsprobleme sind auch erledigt.


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