抛出异常,除非断点后 运行

Exception thrown, except if run after breakpoint

我在尝试删除文件时 运行 遇到了一些奇怪的行为。下面是一个快速代码示例:

if (File.Exists(filePath))
{
    File.Delete(filePath);
}

奇怪的行为是在尝试删除文件时抛出 System.IO.IOException:

System.IO.IOException
HResult=0x80070020
Message=The process cannot access the file 'C:\ProgramData\Path\To\File.sqlite' because it is being used by another process.
Source=mscorlib

在我们的应用程序中,我们仅在 using 语句中访问文件以避免任何持久保留。该文件是一个 sqlite 数据库,没有持久或打开的连接。

这似乎是一个很正常的问题。向代码添加断点时会出现奇怪的行为。例如,如果我们在上面添加一个 Console.WriteLine 语句,中断该语句,然后继续:

<x> Console.WriteLine("Break");
    if (File.Exists(filePath))
    {
        File.Delete(filePath);
    }

没有抛出异常。

如果我们这样添加断点:

    Console.WriteLine("Break");
    if (File.Exists(filePath))
    {
<x>     File.Delete(filePath);
    }

或者像这样:

    Console.WriteLine("Break");
<x> if (File.Exists(filePath))
    {
        File.Delete(filePath);
    }

抛出异常

除了更改断点外,其他都运行完全一样。我们可以可靠地重现此行为。我对这种行为做了一些研究,但找不到任何适用的东西。我很好奇这种行为是否在任何地方都有记录,或者我是否遗漏了任何明显的东西。

编辑:我忘记添加的一些注意事项,我们可以在多台不同的机器上重现此行为。添加 Thread.Sleep() 不会改变行为。

非常感谢任何见解!

几个小时后,一些Google,很多头发都被拔掉了,我已经弄清楚了这个行为的原因。

根据我的发现,这个问题是由于垃圾收集没有按我们预期的那样完成造成的。

我们所有的 SQLite 语句都包含在 using 中,确保调用 Dispose()。出于某种原因,垃圾收集看起来不像 运行,并且一些文件锁仍然存在。当我们添加断点时,似乎有什么东西在幕后启动了垃圾收集。

添加以下内容足以让事情按我们的预期进行:

GC.WaitForPendingFinalizers();