Entwickler-Ecke

Dateizugriff - Deadlock bei Dateiverschiebung


Flamefire - Sa 12.06.10 12:51
Titel: Deadlock bei Dateiverschiebung
Ich habe ein seltsames Problem:
Ich erstelle eine Datei im temp Ordner, bau die dort aus einer existierenden neu auf und verschiebe sie dann an den ursprünglichen Ort.
So weit alles klar.
Dafür gibt es 2 Varianten:
1) Datei umkopieren, dann QuellDatei löschen -->Langsam

Delphi-Quelltext
1:
2:
    Result:=CopyFile(PChar(tmpDir+fdestName),PChar(fSrcName),false);
    Windows.DeleteFile(PChar(tmpDir+fdestName));

2) ZielDatei löschen, Quelldatei "umbennen" -->Schneller

Delphi-Quelltext
1:
2:
    if(FileExists(fsrcName)) then Windows.DeleteFile(PChar(fsrcName));
    Result:=RenameFile(PChar(tmpDir+fdestName),PChar(fSrcName));


Beide Varianten funktionieren mit dem gewünschtem Effekt
Nur habe ich bei der 2. Variante das Problem, dass sich die Anwendung danach vollständig aufhängt.
Ich habe alles rausgenommen, dass danach noch auf die Datei zugreifen könnte o.ä. wenn ich den Code 2) durch 1) ersetze kommt es auch nicht zu dem Fehler.

Woran liegt das?
System: Win7 Pro 64Bit; D2009


ALF - Sa 12.06.10 14:10

Hi, Ich vermute mal was :gruebel:
Im ersten Fall überschreibst Du die Original Datei und löscht die "Temp" Datei.
Im zweiten löscht Du die Original Datei und änderst den Namen der "Temp" Datei.
Bist Du sicher das Du ohne Prüfung die "Temp" und Original Datei nicht weiter verwendest?
Denn die "Temp" Datei existiert ja danach nicht mehr und die Original Datei (evtl im anderm Verzeichnis) auch nicht mehr!
Wie gesagt vermutung!

Was evtl die Zeiteinsparung betrifft hätte ich meine Zweifel.
Beispiel: Orignaldatei in C:\meinedatei\ , "Temp" Datei in C:\Temp\ . Irgendwann musst Du die Datei ja auch wieder in C:\meinedatei\ kopieren.

Gruss Alf

P.S. kompliziert das richtig zu Formulieren!


delfiphan - Sa 12.06.10 14:36

Sofern es keine Konsolenapplikation ist, probier's mal mit EurekaLog: http://blog.eurekalog.com/how-to-debug-applications-hang/


Bergmann89 - Sa 12.06.10 14:57

Hey,

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Was evtl die Zeiteinsparung betrifft hätte ich meine Zweifel.
Beispiel: Orignaldatei in C:\meinedatei\ , "Temp" Datei in C:\Temp\ . Irgendwann musst Du die Datei ja auch wieder in C:\meinedatei\ kopieren.
Wenn sich die Datein auf dem selben Datenträger befinden reicht das umbennen, also wenn ich "C:\Test\was_weiß_ich.txt" in "C:\neu.txt" umbennen, dann wird nix kopiert, sondern nur der Pfad geändert, physisch bleibt die Datei da wo sie ist. Erst wenn man beim umbennenen einen anderen Datenträger als bei der Quelldatei angibt, wird kopiert oder eher gesagt ausgeschnitten...

@Flamefire: Du kannst dir ja mal einene Haltepunkt vor uns nach dem kopieren/umbennen setzten und dann mir Unlocker [http://www.chip.de/downloads/Unlocker_18414122.html] gucken, welche Programme die Datei zuz Zeit benutzen, vlt findest du damit den Fehler.

MfG Bergmann.


ALF - Sa 12.06.10 15:37

Hi user profile iconBergmann89. Ich bin davon ausgegangen das er den Namen seiner "Temp" Datei im Tempordner ändert, nicht in seinem original Verzeichnis. War vielleicht blöde von mir Formuliert :oops:
Ansonsten hast Du natürlich recht :wink:

Gruss Alf


delfiphan - Sa 12.06.10 16:59

Wo ist "danach"? Auf irgend einer Codezeile muss er sich ja aufhängen.

Nebenbei: Mit MoveFileEx+MOVEFILE_REPLACE_EXISTING kannst du das, was du willst, in einem Schritt bewältigen (Achtung bei Verwendung auf Netzwerk Shares).


Flamefire - Sa 12.06.10 17:19

Das danach ist unbekannt, jede Funktion von mir bis zum Onclick (inkl) wird verlassen
GUI hängt sich auf.
Kopiert ist aber alles


delfiphan - Sa 12.06.10 17:29

EurekaLog [http://www.eurekalog.com/index_delphi.php] (Advanced Options/Anti Freeze Options) oder MadExcept [http://www.madshi.net/madExceptDescription.htm] (Basic Settings/Runtime Checks/Check for Frozen Main Thread) wird dir die Frage beantworten


Flamefire - Sa 12.06.10 18:40

Habs gefunden:
Hatte davor ein ShellListview (modifiziert für zusätzliche Skins offen)
Und warum auch immer scheint die o.g. Variante damit ein Deadlock zu produzieren. Irgendwo wird bei RootChanged ein TThread.WaitFor aufgerufen, dass auf MultipleObjects wartet. Aber das kommt nie an.
Habs jetzt mit den Standart Delphi ShellListview gemacht. Da ein paar Bugs gefixt und läuft https://forums.embarcadero.com/thread.jspa?threadID=9627

Blockierte Threads wurden nicht angezeigt. Vermutlich weil der ein Timeout von 1s hatte, und dann nochmal wait aufruft, so dass es schon fast busy waiting wird.