Benutzer mit den meisten Antworten
Dispose Frage

Frage
-
Hallo,ich habe Funktionen mit Templates, also viele Files mit anderen Typen.
Die deserialisiere ich und serialisiere ich.
Wenn ich jetzt für einen Typ die Datei exklusiv öffne, es passiert irgendwas
wird die Datei nicht freigegeben, kann dann auch defekt sein.Da würde ja die Dispose ins Spiel kommen.
Wie mache ich das?
Ich müsste ja im Destruktor von der aufrufende Klasse überall noch Dispose aufrufen,
da kenne ich den Typen nicht mehr.
Grüße Sandrapublic static class TestSerializer<T> { private static HelpToSerialize<T> _MySerializer = null; public static HelpToSerialize<T> MySerializer { get { if (_MySerializer == null) _MySerializer = new HelpToSerialize<T>(); return _MySerializer; } } } public int SaveFile<T>(string file, T dataObject, bool exclusive = false) { TestSerializer<T>.MySerializer.ExclusiveSerializeObject(file, dataObject); TestSerializer<T>.MySerializer.CloseFile(); TestSerializer<T>.MySerializer.Dispose();
Antworten
-
Hallo Sandra,
Das <T> ist nicht das Problem. Dein Problem ist, dass Du Dich (wieder mal) an den zusammengeklaubten Code klammerst.
Siehe vorherige Antwort und beerdige die statische Klasse, verlagere den Serializer in die Klasse (und verpasse ihr das <T>). Alternativ (wenn hier auch weniger sinnvoll) kann man generische Parameter auch bei Methoden verwenden.
Gruß Elmar
- Als Antwort markiert Sandra Bauer Freitag, 16. September 2016 15:04
Alle Antworten
-
Hallo Sandra,
so wirklich sehe ich hier keinen Grund, warum du IDisposable mit der Dispose-Methode brauchen solltest.
Wenn du etwas serialisierst und in eine Datei schreibst, dann geschieht das letzten Endes über einen Stream. Dieser wird am Anfang mit Schreibrechtengeöffnet, dann wird der Inhalt der Datei geschrieben und am Ende wird er geschlossen. Viele Methoden von .NET kapseln das soweit ab, dass man nichts mehr von dem Stream direkt mitbekommt.
Du wirst aber vermutlich trotzdem irgendwo einen Stream haben der wieder geschlossen werden muss. An dem bisschen Code den du uns zeigst zusammen geraten vermute ich, dass der Stream lediglich innerhalb der SaveFile-Methode gebraucht wird. Entsprechend kannst du darin einen using-Block verwenden:
using(var stream = File.OpenWrite(fileName)){ //schreibe in den Stream }
Dieser Block schließt beim verlassen (egal ob mit oder ohne Exception) den Stream wieder.
Alternativ kannst du auch nach dem schreiben die Close-Methode aufrufen. (Oder Dispose wie es der using-Block macht, in den meisten mir bekannten Fällen agieren aber beide Methoden gleich.)
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets -
Hallo Sandra,
da es wohl aus dem Code der letzten Diskussion geht:
Doppelt genäht hält hier nicht besser ;)
Dispose tut nichts weiter als CloseFile. Zudem erklärt es Instanz für "ungültig", was mehr ein Sicherheitsmerkmal gegen Programmierfehler darstellt. Wenn Du mit der Verarbeitung fertig bist, kannst Du das eine oder andere tun, wobei man das Dispose via using verwendet könnte.
Beachte die Anmerkung, die ich in der anderen Diskussion bezüglich des exklusiven Zugriffs gemacht habe.
Gruß Elmar
-
Hallo Zusammen,
ja es geht um das Beispiel.
Das Problem wo ich sehe, ist, ich habe Dateien auf, warum auch immer nicht mehr geschlossen.
Jetzt beende ich das Program, weil das dann doch noch gehen würde.
Dann wäre es ja hilfreich die exklusiv geöffneten Dateien zu schließen.Daraus folgt ja, dass ich T nicht mehr kenne, so dass ich irgendwie eine Schleife durchlaufen könnte
und Dipose, was CloseFile zur Folge hat, aufzurufen.
Grüße Sandra -
Hallo Sandra,
was hat der generische Parameter damit zu tun?
Speichere eine Instanz der Klasse (mit ausgefülltem T) solange wie Du sie brauchst.
Auch sollte der Klassenentwurf so erfolgen, dass man z. B. using sinnvoll nutzen kann:
public void ProcessFile<T>(string file) { // selbst sollte es Probleme geben wird Dispose ausgeführt using (var instance = TestSerializer<T>.MySerializer.ExclusiveSerializeObject(file)) { // Sperre die Datei (ggf. direkt bei Deserialize) instance.OpenFile(); // lese dataObject T dataObject = instance.Deserialize(); // mache was mit dataObject // schreibe dataObject sofern geändert instance.Serialize(dataObject); // schliesse Datei instance.CloseFile(); } }
wobei jeweils Teile davon weglassen kann, also nur Lesen; nur Schreiben etc.
Vor allem aber sollte die Datei durchgängig im Zugriff bleiben und nicht auf einzelne Methoden verteilt werden - dann ist es dahin mit der "Exklusivität".
Gruß Elmar
-
Hallo Elmar,ja Du hast wieder recht.
Man macht eine Funktion, liest die Datei ein, öffnet diese exklusiv.Übergibt das Objekt evtl. per ref der Barbeitungsfunktion.Serialisiert und schließt das File.Passiert irgendwas, tritt aufgrund von using die Dispose auf und schließt somit die Datei.OK, wenn ich es richtig verstanden habe, super. Danke wieder für den Tipp, für das Konzept.Problem:
Fehler 23 "T": Der in einer using-Anweisung verwendete Typ muss implizit in System.IDisposable konvertiert werden können. C:\test\FileManager.cs
Kann es nicht kompilieren.
Viele Grüße Sandrapublic class HelpToSerialize<T> : IDisposable { ..... public static class TestSerializer<T> { private static HelpToSerialize<T> _MySerializer = null; public static HelpToSerialize<T> MySerializer { get { if (_MySerializer == null) _MySerializer = new HelpToSerialize<T>(); return _MySerializer; } } } public void ProcessFile<T>(string file) { // selbst sollte es Probleme geben wird Dispose ausgeführt using (var instance = TestSerializer<T>.MySerializer.ExclusiveDeserializeObject(file)) { //// mache was mit dataObject TestSerializer<T>.MySerializer.ExclusiveSerializeObject(file, instance); TestSerializer<T>.MySerializer.CloseFile(); //// schreibe dataObject sofern geändert //instance.Serialize(dataObject); //// schliesse Datei //instance.CloseFile(); } }
-
Hallo Sandra,
wie bereits angedeutet, wirst Du Dein Klassenaufbau ändern müssen:
- Statische Elemente vertragen sich nicht mit IDisposable, das funktioniert nur mit Instanzen (Objekten).
- Der Konstruktor sollte "entlastet" werden und nicht zu viele Aufgaben übertragen werden.
Wenn Du Dir meine ursprünglichen Lösungsansatz noch mal anschaust, sollte Dir ein Umschreiben selbst gelingen.
Gruß Elmar
-
Hallo Elmar,
// selbst sollte es Probleme geben wird Dispose ausgeführt using (var instance = TestSerializer<T>.MySerializer.ExclusiveDeserializeObject(file)) { ok, using kann hier nicht gehen, weil diese Funktion ein T zurückliefert, das ist das Problem. HelpToSerialize<T> test = new HelpToSerialize<T>(); T test2 = test.ExclusiveDeserializeObject(file); using (var instance = test.ExclusiveDeserializeObject(file) as T) //as System.IDisposable) { //// mache was mit dataObject
Wenn using, dann muss der Rückgabewert IDisposable implementieren.
Das ist ja so nicht der Fall.Sehe ich das dann richtig?
Ich glaube das hat nicht direkt mit static zu tun.Dein Beispiel, anderer Thread habe ich nochmals angeschaut
ist dann so mit dem using nicht umsetzbar.Lese Datei -- Deserialisieren
MacheWas , evtl. Objekt übergeben als ref, bearbeiten, aktualisieren
SchreibeDatei -- SerialisierenViele Grüße Sandra -
Hallo Sandra,
Das <T> ist nicht das Problem. Dein Problem ist, dass Du Dich (wieder mal) an den zusammengeklaubten Code klammerst.
Siehe vorherige Antwort und beerdige die statische Klasse, verlagere den Serializer in die Klasse (und verpasse ihr das <T>). Alternativ (wenn hier auch weniger sinnvoll) kann man generische Parameter auch bei Methoden verwenden.
Gruß Elmar
- Als Antwort markiert Sandra Bauer Freitag, 16. September 2016 15:04