C # CreateDirectory ведет себя странно — не создает каталог

#c# #file-io

#c# #file-io #каталог

Вопрос:

Я удаляю каталог, если он существует, и заново создаю этот каталог.

Мой код выглядит так:

                 if (Directory.Exists(destFolder))
                {
                    Directory.Delete(destFolder, true);
                    DirectoryInfo dirInfo = Directory.CreateDirectory(destFolder);
                }
                else
                {
                    Directory.CreateDirectory(destFolder);
                }
  

Проблема, с которой я сталкиваюсь, заключается в следующем: если каталог уже содержит файлы, и этот каталог в настоящее время открыт в одном из окон проводника Windows (даже если ни один файл не открыт ни в одном приложении), то:

  1. Каталог.Удалить удаляет каталог, и окно проводника автоматически переходит к родительской папке.
  2. CreateDirectory не выдает никакой ошибки, но DirectoryInfo, возвращаемый им, содержит, существует как false .

Из-за этого позже в моей программе, когда я пытаюсь создать файлы в этом каталоге, я получаю сообщение об ошибке: «Не удалось найти часть пути»

Почему такое поведение и каково решение?

Спасибо.

РЕДАКТИРОВАТЬ 1: иногда DirectoryInfo.Exists возвращает true, но каталог фактически не существует в проводнике!

Комментарии:

1. В моем тестовом Directory.Exist и DirectoryInfo.Exist возвращают true после удаления и повторного создания.

2. Проверьте мое РЕДАКТИРОВАНИЕ выше. Можете ли вы проверить, действительно ли каталог был создан, хотя Exists = true ? Вы убедились, что в каталоге есть файлы, и каталог открыт в одном из окон проводника?

3. Я поставил поток. Спящий режим (100) раньше, он работает нормально.

4. Есть ли вероятность, что в этой папке есть файлы, доступные только для чтения?

5. Многим программам нравится открывать дескриптор каталога. Чаще всего потому, что такая программа использует эквивалент FileSystemWatcher (как это делает Explorer). Или потому, что каталог является средой программы. CurrentDirectory . Этот дескриптор открывается с помощью эквивалента FileShare . Удалить. Другими словами, удаление работает просто отлично, но на самом деле оно не исчезнет, пока все дескрипторы не будут закрыты. Последнее предложение является проблемой, CreateDirectory() не может добиться успеха, пока это не произойдет. Сколько времени это займет, совершенно непредсказуемо. Вы можете переименовать каталог или переместить его в корзину.

Ответ №1:

Операции файловой системы не синхронны.

Функция RemoveDirectory помечает каталог для удаления при закрытии. Поэтому каталог не удаляется до тех пор, пока не будет закрыт последний дескриптор каталога. Как вы видите, на самом деле каталог не будет удален, пока все его дескрипторы не будут закрыты, но Directory.DeleteDirectory все будет нормально. В вашем случае это также, скорее всего, такая проблема параллелизма — каталог на самом деле не создается во время выполнения Directory.Exists . Таким образом, вы можете использовать функцию RemoveDirectory и в вашем случае.

Или вы можете периодически проверять его с помощью кода, если хотите использовать в противном Thread.Sleep() случае.

             if (Directory.Exists(destFolder))
            {
                Directory.Delete(destFolder, true);     
                Thread.Sleep(1000);
                DirectoryInfo dirInfo = Directory.CreateDirectory(destFolder);
            }
            else
            {
                Directory.CreateDirectory(destFolder);
            }
  

Еще одно решение:

 if (Directory.Exists(destFolder))
        {
            DirectoryInfo di = new DirectoryInfo(destFolder);

            foreach (FileInfo file in di.GetFiles())
                file.Delete();

            foreach (DirectoryInfo dir in di.GetDirectories())
                dir.Delete(true);

            DirectoryInfo dirInfo = Directory.CreateDirectory(destFolder);

        }
  

Комментарии:

1. ОК. Я приму это, если не получу какое-либо другое альтернативное решение без использования Thread . Сон

2. @viveknuna, хорошие два метода.

Ответ №2:

Поскольку вы просили решение, похожее на решение вивека нуны, которое не использует Thread .Сон:

Вы также можете использовать FileSystemWatcher для отслеживания удаления каталога. В обычном случае это должно быть быстрее, чем поток.Сон.

Однако, если вы выберете этот маршрут, также установите таймер и проверьте, исчез ли каталог без вашего уведомления. FileSystemWatcher автоматически завершает работу, когда система, на которой размещен диск, не поддерживает уведомления.