【问题标题】:Exception thrown, except if run after breakpoint抛出异常,除非在断点之后运行
【发布时间】:2019-06-24 19:57:53
【问题描述】:

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

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() 不会改变行为。

非常感谢任何见解!

【问题讨论】:

  • 您的代码是否有另一部分并行或异步访问?
  • 我们确实有一些部分是并行运行的,但是,此时代码中的所有内容都在同一个线程上同步运行
  • 你能举一个最小的可重现的例子吗?
  • 您提到您还有其他并行运行的东西。请注意,目录和文件枚举也会导致打开句柄,因此请检查您的其他线程。
  • @JuanR 感谢您的提醒!我一定会检查的

标签: c# .net debugging breakpoints


【解决方案1】:

几个小时后,一些谷歌和许多头发被拔出,我已经找出了这种行为的原因。

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

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

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

GC.WaitForPendingFinalizers();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    • 2011-03-05
    相关资源
    最近更新 更多