Перемещение и перезапись файла c # - PullRequest
4 голосов
/ 08 января 2012

Я разрабатываю многопоточное приложение. У меня есть где-то в моем коде:

File.Delete(sidetapedata);
File.Move(sidetapedata2, sidetapedata); //sidetapedata and sidetapedata2 are two file paths that correspond to sidetapedata.txt and sidetaptdata2.txt in some directory.

Вторая строка иногда работает нормально, а иногда - IOException:

Cannot create a file when that file already exists.

Есть еще один поток, который обращается к файлу sidetapedata, но он только читает этот файл, без операций записи. Я использую замки для защиты условий гонки. Не знаю, почему это происходит.

ОБНОВЛЕНИЕ : даже когда отладчик Visual C # показывает мне это исключение, заглядывая в каталог, содержащий эти файлы, я вижу, что нет файла sidetapedata.txt, но есть sidetapedata2.txt файл!

ОБНОВЛЕНИЕ2 : Кроме того, это происходит только тогда, когда sidetapedata.txt и sidetapedata2.txt оба не заполнены

Ответы [ 3 ]

8 голосов
/ 08 января 2012

Не уверен, почему это произойдет, если в файловой системе не будет вызвано какое-либо событие с помощью вызова Delete, что означает, что он не на самом деле был удален до тех пор, пока не будет возвращен вызов.Несколько вариантов:

  • Вы можете зациклить (с каким-то максимальным числом циклов перед ошибкой), где вы проверяете существование файла перед попыткой перемещения, и ненадолго спать, если он все еще существует после удаления
  • Вместо перемещения можно использовать File.Copy(sidetapedata, sidetapedata2, true) - copy , а затем удалить исходный файл.Это будет менее эффективно, если предположить, что перемещение будет обработано простым изменением записи в каталоге файловой системы (а не копированием данных)
  • Вы можете использовать File.Move в целевом файле вместо File.Deleteчтобы переместить его на какое-то другое безопасное имя файла, а затем удалить его, надеясь, что Move более атомарный, чем Delete.

I подозреваемый поток не имеет значенияздесь - я предлагаю вам написать короткую, но полную программу для проверки этого, чтобы вы могли исключить ее (и легко проверить обходные пути).

3 голосов
/ 08 января 2012

Я не уверен, что это то же самое для .NET, но в соответствии с win32 DeleteFile Ссылка API:

Функция DeleteFile помечает файл для удаления при закрытии. Поэтому удаление файла не происходит до тех пор, пока не будет закрыт последний дескриптор файла.

Таким образом, вероятно, существует промежуток времени между возвращением вызова Delete и Windows, закрывающей последний дескриптор файла. Похоже, вы звоните Move в этот период времени.

0 голосов
/ 13 ноября 2015

Согласно этому ответу : используйте FileStream с FileShare

FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...