Flush StreamWriter at the end of its lifetime

人盡茶涼 提交于 2019-12-25 06:50:57

问题


I have a singleton-like class that can do some logging output:

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

    private Foo()
    {
        this.os = System.IO.File.CreateText( "D:/tmp/test" );
    }

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

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

When I use that in a sample program like

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

the file is being created, but no output is written. I assume this is because the StreamWriter has never been flushed.

I tried to repair the class by calling to Close() in ~Foo():

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

but this yields a ObjectDisposedException. Apparently Foo.os has already been disposed when Foo's destructor is called.

How do I ensure that my StreamWriter is flushed "at last"?

EDIT

Setting this.os.AutoFlush = true; works. Adding a Flush() method to Foo and calling it in appropiate places does as well, but I'm interested if there any way of doing without.


回答1:


You can use StreamWriter which does have a Flush method.

There is another option for what you are trying to accomplish, you can use File.AppendAllText and will work. This way the StreamWriter is not open all the time.

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);
   }
}



回答2:


First of all, using a singleton creates problems in its own right, and this did not need another proof. Here, it's cleanup for a disguised global. The StreamWriter does not auto-flush on program end and according to the documentation,

You must call Close to ensure that all data is correctly written out to the underlying stream.

Thanks to an answer to "Self-closing StreamWriter singleton" from @PeterDuniho a possible solution could be changing the constructor to

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

Considering the problem of calling Close() in the destructor, I should not have ignored the "finalizers are not of much use anyway" written all over the place. In this case, as garbage collection does not use a specific order, the StreamWriter object has already been collected and cannot be closed in its resurrected zombie state.



来源:https://stackoverflow.com/questions/36500967/flush-streamwriter-at-the-end-of-its-lifetime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!