Невозможно сохранить конфигурацию в файл несколько раз

У меня есть код, включая модульные тесты, который пытается несколько раз сохранить файл конфигурации. Когда я пытаюсь сохранить файл конфигурации во второй раз, я получаю эту ошибку:

Не удалось сохранить конфигурацию в файл [FileName]

Мой код в основном делает это:

{
Configuration config = ConfigurationManager.OpenExeConfiguration(configName);
...change some values...
config.save();
}

а потом еще раз

{
Configuration config = ConfigurationManager.OpenExeConfiguration(configName);
...change some values in a different way...
config.save();
}

Когда я выполняю config.save во второй раз, возникает 10-секундная задержка, а затем я получаю сообщение об ошибке. Кто-нибудь знает, как «разблокировать» этот файл?


Я попытался сохранить экземпляр переменной конфигурации, то есть «в области видимости», но это не сработало.

private static Configuration GetConfiguration(string configName)
        {
            Configuration retval;
            if (_configs == null) _configs = new Dictionary<string, Configuration>();
            if (_configs.TryGetValue(configName, out retval)) return retval;
            retval = ConfigurationManager.OpenExeConfiguration(configName);
            _configs.Add(configName, retval);
            return retval;
        }

а потом

{
Configuration config = GetConfiguration(configName);
...change some values...
config.save();
}

вместе с

{
Configuration config = GetConfiguration(configName);
...change some values in a different way...
config.save();
}

person jerrylagrou    schedule 23.10.2014    source источник


Ответы (2)


Уг. Я вызывал проблему в другом месте своего кода.

У меня была такая функция:

    private bool FileHasString(string filename, string searchString)
    {
        string content = (new StreamReader(filename)).ReadToEnd();
        return content.IndexOf(searchString) > 0;
    }

Я предположил, что когда считыватель потока вышел из области действия, блокировка файла закончилась. Замок, по-видимому, не работал, и это было причиной проблемы.

Это работает намного лучше.

    private bool FileHasString(string filename, string searchString)
    {
        var sr = new StreamReader(filename);
        string content = sr.ReadToEnd();
        sr.Close();
        return content.IndexOf(searchString) > 0;
    }

Спасибо за помощь.

person jerrylagrou    schedule 23.10.2014
comment
Ага; работа с файлом как с файлом сведет на нет все усилия ConfigurationManager по обеспечению параллелизма. Единственный рефакторинг, который я бы предложил, — это использование конструкции блока using: using(var sr = new StreamReader(filename)){ string content = ... }. Это гарантирует, что StreamReader и его дескриптор файла будут удалены, даже если возникнет исключение, и обеспечивает согласованный, чистый способ работы с объектами IDisposable. - person KeithS; 24.10.2014

Можно ли оставить config между этими двумя блоками кода, чтобы не загружать его во второй раз?

Логика, лежащая в основе ConfigurationManager и пространства имен System.Configuration, на самом деле довольно сложна, потому что конфигурация, которую он создает, не из одного файла, даже если вы специально запрашиваете конфигурацию EXE. Например, возможно, что файл user.config поврежден, что не позволяет загрузить всю конфигурацию EXE. Я видел, как это случалось больше раз, чем я могу сосчитать, и лучшее известное мне решение — просто удалить конфигурацию пользователя и начать заново. Точно так же возможно, что файл user.config заблокирован, потому что сам ConfigurationManager что-то делает с ним.

person KeithS    schedule 23.10.2014
comment
Я пробовал это. Может быть, я сделал это неправильно. Вот что я сделал. - person jerrylagrou; 23.10.2014