Если вы используете [FileAccess]::Read
без явного указания режима общего доступа к файлам, то, если файл уже открыт, его повторное открытие будет успешным, только если он был первоначально открыт в режиме общего доступа к файлам [FileShare]::ReadWrite
(даже если выВы запрашиваете только чтение , метод по умолчанию запрашивает запись доступ тоже), тогда как ваша Read-Write
функция (разумно) использует только [FileShare]::Read
.
Ваша непосредственная проблема исчезнет, если вы откроете свой файловый поток только для чтения в режиме общего доступа к файлам [FileShare]::ReadWrite
:
[System.IO.FileStream]::new(
$path,
[System.IO.FileMode]::Open,
[System.IO.FileAccess]::Read,
[System.IO.FileShare]::ReadWrite # !! required
)
Это позволяет обоим другим читателям одновременно работатьдоступ, а также один-единственный (read +) пишущий (который, возможно, открыл файл первым).
Однако, файл, переписываемый , перезаписывается при чтении другими, может бытьпроблематично , поэтому для надежной и предсказуемой операции Я предлагаю другой подход :
Примечание: Этот ответ к связанному вопросу показывает более простой вариант* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1042 * *вашего файла , затем замените оригинал.
Этот требует явной синхронизации для координации между потенциальными модуляторами обновления , чтобы сериализуйте updates , чтобы обновления не перезаписывали друг друга.
Этого можно добиться с помощью отдельного файла блокировки (сторожевого файла) с именем, скажем, updating
, который действуетв качестве индикатора для других потенциальных авторов, что обновление находится в процессе.
Майк Кристиансен (сам ОП) в итоге также сохранил имя пользователя блокирующего пользователя в этом файле, чтобы предоставить обратную связьдругие потенциальные шкафчики.
Когда запрашивается модификация :
Продолжайте попытки в цикле до создания файла блокировкиupdating
завершается успешно, если файл уже существует.
- (Re) - создание файла
updating
сигнализирует другим потенциальным авторам, что изменение началось.Читатели, напротив, могут продолжать читать в этот момент.
Создать (временную) копию текущего XML-файла и выполнить там изменения..
- В итоге сам Майк просто изменил копию файла в памяти , что упрощает задачу (если у вас достаточно памяти для чтения файла в целом).
Заменить оригинальный файл измененной копией - используйте цикл повторных попыток, пока копирование поверх / перезапись оригинала не будет успешной, учитывая, что другие читатели могут временно предотвратить удаление (повторное создание) /переписать исходный файл.
Удалить файл updating
, сообщая другим потенциальным модификаторам, что обновление завершено.
- Убедитесь, что файл всегда очищен (
try .. finally
), потому что если он задержится, это заблокирует будущие обновления;вам также может понадобиться механизм тайм-аута, который при ожидании удаления существующего файла в конечном итоге заставляет удалить, если можно предположить, что предыдущий апдейтер вышел из строя.
Что касается чтение доступ:
Хотя никаких изменений не происходит, одновременный доступ для чтения должен работать нормально.
Пока файл XML заменяется временным копированием / перезаписью, открытие файла для чтения не удастся на время операции копирования файла / операция записи, поэтому вам потребуетсятам тоже повторная петля.
Код, который в конечном итоге использовал Майк, можно найти здесь .