SSD驱动器上的奇怪目录删除行为

时间:2011-05-16 20:41:38

标签: .net file directory delete-file

目录c:\ test中包含50个左右的文件,没有子目录。

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

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

Drive C是Intel的X25-M80 SSD驱动器,操作系统是支持TRIM的Windows 7 64位,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都不应该是阻塞函数调用 由于启用了TRIM支持,
  • 是否在SSD上“作弊”?

6 个答案:

答案 0 :(得分:16)

之前我遇到过这个问题,但这并不是特定于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);

答案 1 :(得分:5)

在使用反射器探索System.IO.Directory之后,它看起来像.Delete只是FindFirstFile,FindNextFile和RemoveDirectory Win API调用的包装器。关于.Net运行时调用这些API调用或API实现本身没有任何线程或异步。

现在,假设它以某种方式出现TRIM问题,您可以通过打开提升的命令提示符并使用fsutil来禁用TRIM:

fsutil behavior set disabledeletenotify 1

要启用,请使用0作为参数运行相同的命令。

要查询,请使用query作为命令参数:

fsutil behavior query disabledeletenotify 

答案 2 :(得分:2)

是的,它与SSD驱动器无关。我有同样的问题,但只在客户端笔记本电脑上。我使用的是.NET 3.5。就我而言,目录只有一个文件。在Delete完成之前,CreateDirectory似乎首先在内部执行。

这是一个在许多计算机上运行良好三年的代码。客户改成了新的笔记本电脑,代码一直都没有给他。我无法在具有相同配置的开发/测试机器上重现该场景。

答案 3 :(得分:1)

我遇到了同样的问题。我最终只删除了目录@"C:\test"的内容并将新文件复制到目录中。这是我的问题:

Using Directory.Delete() and Directory.CreateDirectory() to overwrite a folder

答案 4 :(得分:0)

我怀疑你在NTFS中发现了以前没有曝光的竞争条件,因为驱动器不存在足够快到达它。我不认为TRIM与它有任何关系(尽管我保留错误的权利!)

无论哪种方式,处理此问题的正确方法是将代码置于重试循环中:

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

        Thread.Sleep(100);
        continue;
    }        
}

答案 5 :(得分:-1)

如果这确实是应用程序代码,请注意您确实要删除名为“est”的目录!

逃离你的路径为“c:\ test”或使用@ operator @“c:\ test”。