Переименование каталога блокирует переименованный 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 и посмотрите, что именно заблокировало этот каталог после вашего переименования:

http://technet.microsoft.com/en-us/sysinternals/bb896645

Другие вопросы по тегам