系统.IO.IOException:由于被另一个进程使用,无法访问文件。

4
我正在使用一个FileSystemWatcher来监视日志文件的更改。
这个日志文件是由第三方应用程序写入的。
一旦触发了更改,我尝试使用以下方法读取文件:
using (FileStream fs = new FileStream(e.FullPath, FileMode.Open, 
    FileAccess.Read, FileShare.ReadWrite))
{
    StreamReader sr = new StreamReader(fs);
    string s = sr.ReadLine();
}

有时候它会在using那一行失败。
其他时候,它会在sr.ReadLine()那里失败,我猜测这是因为第三方系统正在访问该文件。
我认为通过设置FileAccess.Read,我应该能够始终读取文件?
我该如何确保这不会导致异常,或者我需要循环直到成功读取为止?

有时候,你可以采用这种方法,只需重试几次(在尝试之间睡眠几百毫秒)。然而,如果第三方应用程序不断地写入日志文件,当第三方应用程序尝试写入日志文件时,你可能会因为打开了日志文件而破坏它... - Matthew Watson
如果其他进程对文件有独占锁定,你除了等待它关闭文件外,没有太多办法。可以启动一个定时器,定期尝试打开该文件。 - JosephHirn
你应该关闭你的StreamReader。 - Sayse
@MatthewWatson 我遇到了你提到的问题。第三方应用程序偶尔无法写入,因为我将其锁定了。有什么解决办法吗? - CathalMF
1个回答

4

简短回答:在读取之前尝试Thread.Sleep(100),然后尽可能快地读取。

我以为通过设置FileAccess.Read,我应该能够始终读取文件?

通过设置FileAccess.Read,您只是表示需要从文件中读取。通过设置FileShare.ReadWrite,您表示您可以在读取文件时允许第三方读写文件。 异常意味着第三方不希望您在他们写入时进行读取。您的第一选择是检查是否可以配置第三方进程以允许其他进程在他们写入时进行读取,但请注意,从正在被写入的文件中读取可能会有问题。

如何确保这不会引起异常,或者我需要循环直到我可以成功读取?

只要第三方需要独占锁定,就无法no way to guarantee 你不会收到异常,但您可以采取一些措施来降低冲突的风险,主要包括:
  • 阅读时不写入
  • 快速读取

阅读时不写入

目前,您正在监视文件并在第三方写入后立即读取。很有可能他们仍在写作时您尝试读取,因此您应该等待一段时间让他们完成。我建议在读取之前使用Thread.Sleep 100毫秒,但这取决于第三方进程的性质; 即如果它每小时刷新日志,则可以等待更长时间,但如果它每秒钟写入,则等待时间较短。

快速读取

请参考这个问题,了解如何快速阅读的技巧。同时请注意,现在您正在重复地阅读整个文件。如果这是一个大的附加文件,则可以选择缓存已经读取的部分,并在下一次读取时Seek到上次已知的位置。这样您就可以跳过之前已经读取过的内容。


你混淆了FileShareFileAccess,而且相当严重。 - Ben Voigt
感谢@BenVoigt,我已经在答案中纠正了错误。 - Ulf Kristiansen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接