Подтвердить что ты не робот

Необычное поведение удаления каталогов на накопителе SSD

Каталог c:\test имеет 50 или около того файлов в нем, никаких подкаталогов.

    If IO.Directory.Exists("C:\test") Then
        IO.Directory.Delete("C:\test", True)
    End If

    IO.Directory.CreateDirectory("C:\test")

Привод C - это SSD-накопитель Intel X25-M80, операционная система - 64-разрядная версия Windows 7 с поддержкой TRIM, Visual Studio - 2008 с целевой средой 3.5. Когда выполняется над кодом, CreateDirectory нарушает выполнение кода без (видимого) исключения. После большой головной боли я обнаружил, что удаление еще не выполнено, когда выполнение временного кода попадает в CreateDirectory. Если я изменю свой код следующим образом:

    If IO.Directory.Exists("C:\test") Then
        IO.Directory.Delete("C:\test", True)
    End If
    Threading.Thread.Sleep(2000)
    IO.Directory.CreateDirectory("C:\test")

тогда все работает так, как ожидалось.

Мои вопросы, помимо очевидной WTF, следующие:

  • не должен IO.Directory.Delete быть вызовом функции блокировки независимо от того, какой диск
  • SSD "обманывает" при удалении из-за включенной поддержки TRIM?
4b9b3361

Ответ 1

У меня были проблемы с этим раньше, но это не относится к дискам SSD. Вам было бы намного лучше сделать ход, а затем удалить:

if(Directory.Exists(dirpath))
{
    string temppath = dirpath + ".deleted";
    Directory.Move(dirpath, temppath);
    Directory.Delete(temppath, true);
}
Directory.Create(dirpath);

Другим способом справиться с этим является цикл до завершения:

if(Directory.Exists(dirpath))
{
    Directory.Delete(dirpath, true);
    int limit = 100;
    while(Directory.Exists(dirpath) && limit-- > 0)
        Thread.Sleep(0);
}
Directory.Create(dirpath);

Ответ 2

После изучения System.IO.Directory с рефлектором это выглядит как .Delete - это всего лишь оболочка вызовов FindFirstFile, FindNextFile и RemoveDirectory Win API. Ничего не происходит нитовым или асинхронным по поводу запуска .NET-вызовов этих вызовов API или самой реализации API.

Теперь, предположив, что это как-то проблема TRIM, вы можете отключить TRIM, открыв приветственную командную строку и используя fsutil:

fsutil behavior set disabledeletenotify 1

Чтобы включить, выполните ту же команду с параметром 0 в качестве параметра.

Для запроса используйте запрос в качестве аргумента команды:

fsutil behavior query disabledeletenotify 

Ответ 3

Да, это не имеет ничего общего с диском SSD. У меня была такая же проблема, но только на клиентском ноутбуке. Я использую .NET 3.5. В моем случае в каталоге был один файл. Кажется, что CreateDirectory выполняет сначала внутренне, пока не завершится удаление.

Это был код, который хорошо работал в течение трех лет на многих компьютерах. Клиент перешел на новый ноутбук, и код для него постоянно не срабатывает. Я не могу воспроизвести сценарий на машинах разработки/тестирования с одинаковой конфигурацией.

Ответ 5

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

В любом случае, правильный способ справиться с этим состоит в том, чтобы поместить код в цикл Retry:

int retries = 3;
while(true) {
    try {
        doTheOperation();
        break;
    } catch (Exception ex) {
        retries--;
        if (retries == 0) {
            throw;
        }

        Thread.Sleep(100);
        continue;
    }        
}

Ответ 6

Если это действительно код приложения, обратите внимание, что вы действительно пытаетесь удалить каталог с именем "est"!

Побег вашего пути, чтобы быть "c:\test" или использовать @operator @ "c:\test".