Переименование каталога блокирует переименованный dir во второй раз, когда я хочу переименовать
У меня проблемы с переименованием директории несколько раз, похоже, файл заблокирован.
// e comes from a objectListView item
DirectoryInfo di = (DirectoryInfo)e.RowObject;
DirectoryInfo parent = Directory.GetParent(di.FullName);
String newPath = Path.Combine(parent.FullName, e.NewValue.ToString());
// rename to some temp name, to help change lower and uppercast names
di.MoveTo(newPath + "__renameTemp__");
di.MoveTo(newPath);
// Trying to cleanup to prevent directory locking, doesn't work...
di = null;
parent = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
Любая помощь очень ценится, потому что первое переименование работает нормально, но при попытке сделать новое переименование в переименованной папке выдается исключение:
Процесс не может получить доступ к файлу, потому что он используется другим процессом. Первое случайное исключение типа "System.IO.IOException" произошло в mscorlib.dll
Итак, при первом переименовании этой папки работает, второй раз выдает исключение, я предполагаю, что приложение удерживает блокировку новой папки, но как обойти это? Я должен быть в состоянии переименовать папку дважды, верно?
3 ответа
Вступление
Чтобы воспроизвести вашу проблему, я создал следующий метод:
private static string RenameFolder(string path, string newFolderName)
{
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo parent = Directory.GetParent(di.FullName);
String newPath = Path.Combine(parent.FullName, newFolderName);
// rename to some temp name, to help change lower and uppercast names
di.MoveTo(newPath + "__renameTemp__");
di.MoveTo(newPath);
return di.FullName;
}
Когда я называю это следующим образом, это работает:
var path = @"C:\Temp\test";
var newPath = RenameFolder(path, "TESt");
newPath = RenameFolder(path, "Test1");
Когда я называю это следующим образом, это не работает:
var path = @"C:\Temp\test";
var newPath = RenameFolder(path, "TESt");
newPath = RenameFolder(newPath, "Test1");
Единственная разница между двумя вызовами состоит в том, что в первой версии я передаю исходное имя, то есть все в нижнем регистре. Во втором случае я предоставляю новое имя, т.е. все в верхнем регистре, кроме последней буквы. Даже спать в течение 20 секунд между двумя вызовами RenameFolder
не меняет это. Странный!
Решение
Если я реализую RenameFolder
вот так это работает в обоих случаях:
private static string RenameFolder(string path, string newFolderName)
{
String newPath = Path.Combine(Path.GetDirectoryName(path), newFolderName);
// rename to some temp name, to help change lower and uppercast names
Directory.Move(path, newPath + "__renameTemp__");
Directory.Move(newPath + "__renameTemp__", newPath);
return newPath;
}
Так или иначе, DirectoryInfo
похоже на регистр чувствительна блокировка на пути.
объяснение
У меня нет никого, может быть, кто-то с немного большим пониманием внутренних путей DirectoryInfo
может пролить свет на это странное поведение.
Важная точка
Не использовать GC.Collect
если не знаешь, что делаешь! Обычно вам не нужно вызывать этот метод.
Мои предыдущие ответы были неверными. Как упомянуто в комментариях, метод MoveTo() обновляет объект DirectoryInfo для представления нового пути, который явно не задокументирован.
Как указывает Даниэль Хилгарт в своем ответе, проблема, вероятно, кроется в другом. Возможно, вам потребуется добавить логику, которая проверяет, когда каталог снова станет доступен.
Возьмите копию Process Monitor и посмотрите, что именно заблокировало этот каталог после вашего переименования: