在静态方法中管理一次性对象

时间:2012-02-01 14:33:33

标签: c# .net static stream disposable

public class SimpleLogger
{
    static readonly string logFile = ConfigurationManager.AppSettings["LogFile"];

    static StreamWriter GetStream()
    {
        return File.Exists(logFile) ?
            File.AppendText(logFile) : File.CreateText(logFile);
    }

    public static void Write(string msg)
    {
        using (var sw = GetStream())
        {
            sw.Write(msg);
        }
    }
}

以上代码无法使用,因为它似乎没有正确关闭/处理流。后续写入会给出“正在使用的文件”IOException。

如果修改了类以使用 非静态 方法,则它似乎可以正常工作。

我不明白为什么会有任何行为差异?

2 个答案:

答案 0 :(得分:7)

处置没问题; GetStream提供了一个开放的作家; Write关闭/处理它 - 已排序。但是,如果我不得不猜测,问题是并发使用 - 即多个线程(特别是在Web应用程序中)同时访问文件 。如果是这种情况,请选择:

  • 使Write(以及对该文件的任何其他访问)同步,因此只有一个调用者可能尝试立即打开该文件
  • 使用已经处理此场景的预先封装的日志框架(这里的常见方法包括同步,还包括:在本地缓冲数据,然后定期推送数据 - 避免一遍又一遍地打开文件)

特别是;您唯一的静态是文件路径本身。因此,使用它作为静态与实例方法之间没有显着差异。

作为旁注,File.AppendAllText在这里可能很有用,但不能避免并发问题。

答案 1 :(得分:3)

我不认为从静态更改为实例会解决问题,因为它们最终都是在静态资源(文件)上竞争。 This回答可能会对您有所帮助。也许如果你把两个方法都保持为静态并声明一个静态同步对象来调用线程来锁定(因为资源本身是静态的)会有帮助吗,例如:

private static object _objectLock = new object();

用于同步从多个线程访问文件,因此:

public static void Write(string msg)      
{        
    lock(_objectLock)
    {  
        using (var sw = GetStream())          
        {              
            sw.Write(msg);          
        }
    }      
}