Переименование каталога блокирует переименованный dir во второй раз, когда я хочу переименовать - PullRequest
2 голосов
/ 15 марта 2011

У меня проблемы с переименованием каталога несколько раз, кажется, что файл заблокирован.

// 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 ]

10 голосов
/ 15 марта 2011

Введение

Чтобы воспроизвести вашу проблему, я создал следующий метод:

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, если не знаете, что делаете! Обычно вам не нужно вызывать этот метод.

1 голос
/ 15 марта 2011

Получите копию Process Monitor и посмотрите, что именно заблокировало этот каталог после вашего переименования:

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

1 голос
/ 15 марта 2011

Мои предыдущие ответы были неправильными.Как упомянуто в комментариях, метод MoveTo () обновляет объект DirectoryInfo для представления нового пути, который не задокументирован четко.в его ответе проблема, вероятно, лежит где-то еще.Возможно, вам потребуется добавить логику, которая проверяет, когда каталог снова станет доступен.

...