尝试删除文件时,我遇到一些奇怪的行为。下面是一个快速的代码示例:
if (File.Exists(filePath))
{
File.Delete(filePath);
}
奇怪的行为是尝试删除文件时抛出System.IO.IOException:
System.IO.IOException
HResult = 0x80070020
Message =该进程无法访问文件'C:\ ProgramData \ Path \ To \ File.sqlite',因为它正在被另一个进程使用。
来源= 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()
不会改变行为。
任何见识都将受到赞赏!
答案 0 :(得分:1)
几个小时后,一些谷歌和许多头发拔了出来,我已经弄清了这种现象的原因。
从我发现的情况来看,此问题是由于垃圾收集未按预期完成所致。
我们所有的SQLite语句都包装在using中,以确保调用Dispose()。由于某种原因,它看起来好像没有在运行垃圾回收,并且保留了一些文件锁。当我们添加断点时,似乎在后台启动了“垃圾回收”。
添加以下内容足以使我们按预期工作:
GC.WaitForPendingFinalizers();