Comportamiento extraño de eliminación de directorio en la unidad SSD


Directorio c:\test tiene 50 o más archivos en él, sin subdirectorios.

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

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

La unidad C es la unidad SSD X25-M80 de Intel, el sistema operativo es Windows 7 64 bits con soporte TRIM, Visual Studio es 2008 con target framework 3.5. Cuando se ejecuta el código anterior, CreateDirectory interrumpe la ejecución del código sin una excepción (visible). Después de mucho dolor de cabeza me di cuenta de que la eliminación aún no se ha hecho por el tiempo de ejecución de código llega a CreateDirectory. Si modifico mi código de esta manera:

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

, Entonces todo funciona como se esperaba.

Mis preguntas al lado de la obvia WTF aquí son:

  • no debería IO.Directorio.Delete sea una llamada a la función de bloqueo sin importar cuál sea la unidad
  • es SSD "trampa" en eliminar debido a la compatibilidad con TRIM habilitado?
Author: Machavity, 2011-05-17

6 answers

He tenido problemas con esto antes, pero esto no es específico de las unidades SSD. Usted sería mucho mejor hacer un movimiento a continuación, eliminar:

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

La otra forma de lidiar con esto es hacer un bucle hasta que se complete:

if(Directory.Exists(dirpath))
{
    Directory.Delete(dirpath, true);
    int limit = 100;
    while(Directory.Exists(dirpath) && limit-- > 0)
        Thread.Sleep(0);
}
Directory.Create(dirpath);
 16
Author: csharptest.net,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-16 21:32:12

Después de explorar System. IO. Directory con reflector, parece .Delete es solo un envoltorio alrededor de las llamadas a la API Win de FindFirstFile, FindNextFile y RemoveDirectory. No hay nada enhebrado o asincrónico en la invocación de.Net runtime de esas llamadas a la API, o la implementación de la API en sí.

Ahora, suponiendo que de alguna manera es un problema de TRIM, puede deshabilitar TRIM abriendo un símbolo del sistema con privilegios elevados y utilizando fsutil:

fsutil behavior set disabledeletenotify 1

Para habilitar, ejecute el mismo comando con 0 como parámetro.

Para consultar, utilice query como argumento del comando:

fsutil behavior query disabledeletenotify 
 5
Author: Ritch Melton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-16 21:23:14

Sí, no tiene nada que ver con la unidad SSD. Yo tenía el mismo problema, pero sólo en una computadora portátil cliente. Estoy usando. NET 3.5. En mi caso, el directorio tenía un solo archivo. CreateDirectory parece estar ejecutándose primero internamente antes de que finalice la eliminación.

Este fue un código que funcionó bien durante tres años en muchas computadoras. El cliente cambió a una nueva computadora portátil y el código falla constantemente para él. No puedo reproducir el escenario en máquinas de desarrollo / prueba con la misma configuración.

 2
Author: Bharat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-06 16:07:10

Yo tenía el mismo problema. Terminé borrando solo el contenido del directorio @"C:\test" y copiando los nuevos archivos al directorio. Ese fue mi problema:

Usando Directorio.Eliminar () y Directorio.CreateDirectory() para sobrescribir una carpeta

 1
Author: A-Sharabiani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:58:46

Sospecho que ha encontrado una condición de carrera en NTFS que anteriormente no estaba expuesta ya que no existían unidades que fueran lo suficientemente rápidas como para golpearla. No creo que TRIM tenga nada que ver con ello (¡aunque me reservo el derecho de equivocarme!)

De cualquier manera, la forma correcta de manejar esto es poner el código en un bucle de Reintentos:

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

        Thread.Sleep(100);
        continue;
    }        
}
 0
Author: Paul Betts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-16 21:32:08

Si ese es realmente el código de la aplicación, tenga en cuenta que realmente está tratando de eliminar el directorio llamado "est"!

Escapar de su camino para ser "c:\test" o utilizar el operador @ @"c:\test".

 -1
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-03 16:35:21