【问题标题】:FileStream.close() does not free file for other processesFileStream.close() 不会为其他进程释放文件
【发布时间】:2013-02-19 10:58:42
【问题描述】:

我在 Page_Load 调用函数中有以下代码。在启动 Visual Studio 后第一次加载页面时,一切正常。
但是之后对文件的任何其他打开调用都会返回IOException: "File is in use by another process",即使在 VisualStudio 解决方案中直接打开文件时也会返回此错误(当然不是异常)

FileStream mailinglist_FileStream = new FileStream(@"\foobarFile.txt", FileMode.Open);
PeekingStreamReader mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream);
//Do some stuff with the file
mailinglist_FileStream.Close();
mailinglist_Reader.Close();
mailinglist_Reader.Dispose();
mailinglist_FileStream.Dispose();

为什么文件仍然被锁定?为什么完全重新启动 Visual Studio 会重置文件? 检查文件属性时,它说:

构建操作:内容
复制到输出目录:不要复制

我只是在阅读这个文件。我可以做一些类似于adLockOptimistic 的事情,以便多个进程可以访问文件吗?

【问题讨论】:

  • 附注:使用 using 语句而不是手动关闭和处理对象

标签: c# asp.net filestream file-access


【解决方案1】:

为什么文件仍然被锁定?以及为什么要完全重新启动 Visual Studio 重置文件?检查文件属性时,它说[...] 我不知道为什么文件仍然被锁定:可能是因为您的代码在流关闭/处置之前失败。

关于“为什么要完全重启 Visual Studio [...]”:因为您可能正在使用 IIS Express 或 ASP.NET Dev Server,它们在您关闭 IDE 时已关闭,因此会锁定文件被释放,因为持有锁的进程不再运行。

关于“为什么文件仍然被锁定?[...]”这可能是因为文件流没有关闭,因为有时线程可能没有成功结束并且锁定没有t 发布。

正如其他答案所说,检查 using 块如何避免 IDisposable 对象不会被处置:

// FileShare.ReadWrite will allow other processes 
// to read and write the target file even if other processes 
// are working with the same file
using var mailinglist_FileStream = new FileStream(@"\foobarFile.txt", FileMode.Open, FileShare.ReadWrite);
using var mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream);
      // Do your stuff. Using blocks will call Dispose() for 
      // you even if something goes wrong, as it's equal to a try/finally! 

我只是在阅读这个文件。我可以做类似的事情吗 adLockOptimistic,让多个进程可以访问文件?

是的,看看File.Open方法和FileShare枚举:

【讨论】:

  • @Matias 关于您的大括号评论:“没有额外的 { }”是使用语言语法的个人偏好。单语句块不需要大括号。 FileShare.ReadWrite 将允许其他进程访问该文件,但它并不能解决文件保持打开状态的问题。不过,很好的例子和优点。
  • 从 C# 8.0 开始,您还可以使用方便的using declarationusing var mailinglist_FileStream = new FileStream(@"\foobarFile.txt", FileMode.Open, FileShare.ReadWrite); using var mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream); // Do your stuff.
  • @OlivierJacot-Descombes 已更新!谢谢!
【解决方案2】:

学习使用using

using (FileStream fileStream = File.Open(@"C:\somefile", FileMode.Open, FileAccess.Read))
{
    ...
}

using 构造可确保在您离开块时关闭文件,即使抛出异常也是如此。

您的问题可能不在此处,而在代码的其他地方。您必须检查所有代码并查找打开文件的位置,但不要将其放在 using 语句中。

【讨论】:

    【解决方案3】:

    尝试使用using 块,它可能无法解决您的锁定问题,但它是一次性对象的更好形式。

    using (FileStream mailinglist_FileStream = new FileStream(@"\foobarFile.txt", FileMode.Open))
    {
        using (PeekingStreamReader mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream))
        {
            ...            
        }
    }
    

    另外,请尝试在mailinglist_FileStream 之前关闭mailinglist_Reader

    【讨论】:

    • 有趣的是,更改顺序后,Page_Load 工作,但我的 catch(IOException) BLock 仍然被执行
    • 在 using 块中调用 Stream.Close 是多余的。
    • 你遇到了什么异常,同一个?尝试注释掉这两条 Close(); 行,因为它们可能被 using 调用。
    • 您可以将多个usings放在同一个缩进级别,并且只有一组{}s。
    【解决方案4】:

    一个老问题,但不幸的是,给出的答案可能不适用于该问题。

    Windows 特有的问题在于 Windows 行为的两个方面:

    a) 当为写入而打开的文件句柄关闭时,Microsoft 反恶意软件服务会打开该文件以检查新写入的数据是否存在恶意软件;

    b) 操作系统本身会在文件的所有句柄关闭后保持文件打开一段时间。该时间可能从几秒到几分钟不等,具体取决于文件的性质和其他因素。

    我们在我们的产品中多次看到这个问题,因此必须为这种情况提供特殊支持 - 我们的内核模式会在文件的最后一个句柄关闭后立即关闭它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 2011-12-04
      • 2010-11-27
      • 2020-10-15
      • 1970-01-01
      相关资源
      最近更新 更多