Управление одноразовыми объектами в рамках статических методов - PullRequest
3 голосов
/ 01 февраля 2012
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 ]

7 голосов
/ 01 февраля 2012

распоряжение в порядке;GetStream доставляет открытого писателя;Write закрывает / удаляет - сортирует.если бы мне пришлось угадывать, однако, проблема заключается в одновременном использовании - то есть нескольких потоках (в частности, в веб-приложении), обращающихся к файлу одновременно .В этом случае параметры:

  • делают синхронизацию Write (и любой другой доступ к файлу), поэтому только один вызывающий может возможно попытаться открыть файл
  • сразу используйте предварительно консервированную структуру ведения журнала, которая уже будет обрабатывать этот сценарий (общие подходы здесь включают синхронизацию, но также: локальную буферизацию данных и затем периодическую отправку данных - избегает открытия файла снова и сноваи снова и снова)

В частности;Ваше единственное статическое состояние - это сам путь к файлу.Поэтому не будет существенной разницы между использованием этого в качестве статического метода по сравнению с экземпляром.

В качестве дополнительного примечания, File.AppendAllText может быть полезно здесь, но не устраняет проблему параллелизма.

3 голосов
/ 01 февраля 2012

Я не думаю, что переход от статического к экземпляру решит проблему, так как все они в конечном итоге конкурируют за статический ресурс (файл). Этот ответ может вам помочь.Возможно, если вы оставите оба метода статическими и объявите статический объект синхронизации для вызова потоков, с которыми нужно заблокировать потоки (поскольку сам ресурс является статическим), это поможет? Например:

private static object _objectLock = new object();

для синхронизации доступа к файлу из несколькихтемы, следовательно:

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