2016-04-08 6 views
0

Ich habe eine Singleton-ähnliche Klasse, die einige Protokollierung Ausgang tun können:Flush Stream am Ende seiner Lebensdauer

Wenn ich in einem Beispielprogramm wie

class Program 
{ 
    private static void Main(string[] args) 
    { 
     Foo.Instance.Log("asdf\n"); 
    } 
} 

verwenden, dass die Datei wird erstellt, aber es wird keine Ausgabe geschrieben. Ich nehme an, dies ist, weil die StreamWriter wurde nie geleert.

Ich habe versucht, die Klasse zu reparieren, indem in ~Foo() zu Close() Aufruf:

~Foo() 
{ 
    os.Close(); 
} 

aber dies ergibt eine ObjectDisposedException. Anscheinend wurde Foo.os bereits entsorgt, wenn der Destruktor Foo aufgerufen wird.

Wie stelle ich sicher, dass mein StreamWriter "endlich" geleert wird?

EDIT

Einstellung this.os.AutoFlush = true; funktioniert. Hinzufügen einer Flush() Methode zu Foo und Aufruf an geeigneten Orten tut auch, aber ich bin interessiert, wenn es einen Weg gibt, ohne zu tun.

+0

Implementieren Sie die [IDisposable Schnittstelle] (https://msdn.microsoft.com/en-us/library/system.idisposable (v = vs.110) .aspx) – Steve

+0

Ich dachte daran, aber in dem angegebenen Beispiel 'Dispose()' wird nicht aufgerufen. – mkluwe

+0

Das ist ein Destruktor. Es ist anders Siehe: http: //stackoverflow.com/questions/339063/what-is-the-difference-between-using-idisposable-vs-a-destructor-in-c – Steve

Antwort

0

Zunächst einmal verursacht die Verwendung eines Singletons Probleme, und das brauchte keinen weiteren Beweis. Hier ist es die Bereinigung für ein getarntes Global. Die StreamWriter nicht automatisch bündig auf Programmende und nach the documentation,

Sie müssen Close aufrufen, um sicherzustellen, dass alle Daten korrekt an den zugrunde liegenden Stream geschrieben wird.

Dank einer Antwort auf „Self-closing StreamWriter singleton“ von @PeterDuniho eine mögliche Lösung der Konstruktor Wechsel zu

private Foo() 
{ 
    this.os = System.IO.File.CreateText("D:/tmp/test"); 
    System.AppDomain.CurrentDomain.ProcessExit += 
     (sender, eventArgs) => this.os.Close(); 
} 

Betrachtet man das Problem der Aufruf Close() im destructor werden könnte, hätte ich nicht ignoriert die " Finalizer sind sowieso nicht von Nutzen "überall auf der Welt geschrieben. In diesem Fall wurde das Objekt StreamWriter bereits gesammelt und kann in seinem wiederauferstandenen Zombie-Status nicht geschlossen werden, da die Garbage Collection keine bestimmte Reihenfolge verwendet.

0

Sie können StreamWriter verwenden, der über eine Flush-Methode verfügt.

Es gibt eine andere Option für das, was Sie erreichen möchten, Sie können File.AppendAllText verwenden und funktionieren. Auf diese Weise ist der StreamWriter nicht immer geöffnet.

class Foo 
{ 
    private static Foo instance; 
    private System.IO.StreamWriter os; 

    private Foo() 
    { 
     this.os = new System.IO.StreamWriter("D:/tmp/test.txt"); 
    } 

    public static Foo Instance 
    { 
     get 
     { 
      if (instance == null) 
       instance = new Foo(); 
      return instance; 
     } 
    } 

    public void Log(string s) 
    { 
     os.WriteLine(s); 
     os.Flush(); 
    } 

    public void Log2(string s) 
    { 
     System.IO.File.AppendAllText(@"D:/tmp/test2.txt",s); 
    } 
}