Datei löschen trotz Garbage Collector

Hi Zusammen!

Folgendes Szenario ist gegeben:

Ich erzeuge programmgesteuert eine Datei, arbeite mit dieser, lösche den Dateihandle (File file = null:wink: und möchte die Datei im Anschluss vom selben Programm wieder löschen lassen. An für sich kein Problem, zumindest in der COM-Welt. In .NET gibt’s aber den Garbage Collector, der den Speicher managed. Das Problem ist nun, dass der Garbage Collector trotz file = null; das file Objekt nicht sofort frei gibt, sondern eben erst wenn es ihm Spass macht. Von aussen ist der GC ebenfalls nicht (an-) steuerbar.

Meine Frage:

Wie kann man nun trotzdem eine Datei zu einem gewünschten Zeitpunkt löschen? Lässt sich das irgendwie erzwingen?

Schon mal Danke!

Sebo

System.GC.Collect(). Aber vielleicht suchst du eher nach File.Delete()…

Danke für die Antwort, aber leider hilft Sie mir nicht weiter.

Die Methode File.Delete verwende ich ja zum Löschen der Dateien, nur wenn noch ein FileHandle auf der Datei liegt (entspricht folgender Windows Fehlermeldung wenn man eine Datei löschen will: „Die Datei wird von einer anderen Person bzw. einem anderen Programm verwendet.“) bricht die Funktion mit einer entsprechenden Fehlermeldung ab. Und den Dateihandle kann ich nur logisch löschen, nicht physisch (das müsste ich aber), denn das macht der GC und der sagt: „Der Aufruf der ReRegisterForFinalize-Methode garantiert nicht, dass der Garbage Collector den Finalizer des Objekts aufruft.“

Jemand noch eine Idee?

Sebo

Hi zusammen!

Habe nun selbst einen „Weg“ gefunden, ist eher ein Mordsumweg, aber besser als gar nix.

Zitat ms-help:

„In Szenarien, in denen Ressourcen zu bestimmten Zeitpunkten freigegeben werden müssen, können Klassen die IDisposable-Schnittstelle implementieren. Deren IDisposable.Dispose-Methode übernimmt die Ressourcenverwaltung und Bereinigungsaufgaben. Bei Klassen, die Dispose implementieren, muss als Teil des Klassenvertrags angegeben werden, ob und wann Klassenconsumer die Methode zur Bereinigung des Objekts aufrufen müssen. In der Standardeinstellung ruft der Garbage Collector die Dispose-Methode nicht auf. Implementierungen der Dispose-Methode können jedoch Methoden der GC-Klasse aufrufen, um das Finalisierungsverhalten des Garbage Collectors anzupassen.“

Sebo

Moien

Ich erzeuge programmgesteuert eine Datei, arbeite mit dieser,
lösche den Dateihandle (File file = null:wink: und möchte die
Datei im Anschluss vom selben Programm wieder löschen lassen.

//Alle Zugriife auf die Datei abschliessen.
file.delete();
file = null;

Wo ist das Problem ?

cu

Hi!
Dass sich die Datei nicht löschen lässt, liegt eventuell auch daran, dass Du ein Objekt, das mit besagter Datei arbeitet, diese noch nicht korrekt freigegeben hat.
Überprüf’ vielleicht mal, ob von allen Readern/Writern, die auf die Datei zugreifen, auch brav deren Dispose() aufgerufen wurde (bzw. alle Streams sauber geschlossen wurden, aber da bist Du vermutlich selbst schon drauf gekommen).
Wenn man das nämlich sauber macht, braucht man nicht versuchen, den Garbage Collector auszutricksen.

Dabei bietet sich übrigens das using() Konstrukt an. Dort wird das Dispose automatisch aufgerufen.

Gruß,
Martin

Hi!

object = null; entspricht object.Dispose(); vorausgesetzt es existiert ein Dispose(). Leider finde ich die schriftliche Quelle meiner „Behauptung“ momentan nicht. Intern ist es sogar so, dass die Dispose Funktion in eine Finalize Funktion „umgewandelt“ wird und vom GC ausgeführt wird.

Wo ist das Problem ?

Ok, dann habe ich das wohl zu allgemein gehalten: Mein Code sieht ungefähr so aus:

//entspricht in meiner Beschreibung dem Dateierzeugen
System.IO.File.Copy(path1, path2);

//Verarbeitung
System.Net.Mail.MailMessage.Attachments.Add(new Attachment(file.Trim()));

System.Net.Mail.MailMessage.Clear();
System.IO.File.Delete(path2); //Exception

Gut, hier lösche ich das MailMessage Objekt nicht, ein Clear() ist aber wie ein object = new object(); und das ist meines Wissens wie ein object = null;

Ich hatte auch mal eine Version, in der das ganze MailMessage Objekt gelöschen wurde. Dabei habe ich mit object = null; und mit object.Dispose(); experimentiert. Funktionierte alles nicht.

Tach zusammen!

Ok, das ganze hier hat sich erledigt! Irgendwie hatte ich wohl einen Knoten im Hirn und ein paar Fehlinfos. Dank Eurer Hilfe funzt jetzt aber alles wie gewünscht! :smile:

Mein neuer Code:

//delete the File handle directly, after this you can delete or move the file for example
for (int i = 0; i

Hi!

object = null; entspricht object.Dispose(); vorausgesetzt es
existiert ein Dispose(). Leider finde ich die schriftliche

Nanana, das wage ich aber stark zu bezweifeln… :smile:

Quelle meiner „Behauptung“ momentan nicht. Intern ist es sogar
so, dass die Dispose Funktion in eine Finalize Funktion
„umgewandelt“ wird und vom GC ausgeführt wird.

Einfach mal ein Mini-Beispiel programmieren und sich die entstehende IL ansehen:

FileStream fs = new FileStream("C:\\Test.txt", FileMode.Open);
fs.Dispose();
fs = null;

liefert

 // Code size 23 (0x17)
 .maxstack 3
 .locals init ([0] class [mscorlib]System.IO.FileStream fs)
 IL\_0000: nop
 IL\_0001: ldstr "C:\\Test.txt"
 IL\_0006: ldc.i4.3
 IL\_0007: newobj instance void [mscorlib]System.IO.FileStream::.ctor(string,
 valuetype [mscorlib]System.IO.FileMode)
 IL\_000c: stloc.0
 IL\_000d: ldloc.0
 IL\_000e: callvirt instance void [mscorlib]System.IO.Stream::smiley:ispose()
 IL\_0013: nop
 IL\_0014: ldnull
 IL\_0015: stloc.0
 IL\_0016: ret

Das Ganze ohne den Aufruf an Dispose() liefert:

 // Code size 16 (0x10)
 .maxstack 3
 .locals init ([0] class [mscorlib]System.IO.FileStream fs)
 IL\_0000: nop
 IL\_0001: ldstr "C:\\Test.txt"
 IL\_0006: ldc.i4.3
 IL\_0007: newobj instance void [mscorlib]System.IO.FileStream::.ctor(string,
 valuetype [mscorlib]System.IO.FileMode)
 IL\_000c: stloc.0
 IL\_000d: ldnull
 IL\_000e: stloc.0
 IL\_000f: ret

Die Aussage, dass das Zuweisen von null dem impliziten Aufruf von Dispose entspricht ist also, mit Verlaub, großer Quark!

Martin

Die Aussage, dass das Zuweisen von null dem impliziten Aufruf
von Dispose entspricht ist also, mit Verlaub, großer Quark!

Jep, ich erlaube! :wink: Hast recht, da bin ich einem Irrtum aufgesessen, wer weiss wo ich das gelesen habe, oder ich hab’s falsch verstanden, wer weiss. Danke!