FileStream和C#中的FileSystemWatcher,奇怪的问题“进程无法访问文件”

我有这个复杂的代码库,它正在侦听某个文件夹上的FileCreated事件。 当文件被创建(其中还包括将文件移动到该文件夹​​)时,我想读取该文件并对其执行某些操作。 它适用于第一个文件,但在所有其他尝试之后抛出exception。 在调试模式下(使用VisualStudio),将抛出错误,但如果我只是单击“继续”…它将工作(没有错误)。

我发布了简化代码,它演示了这个问题。

例如,启动应用程序,单击“开始”按钮,然后“创建新文本文件”

输出是:

Working 

如果您以完全相同的方式创建2ed文件,则输出为:

 Broken: The process cannot access the file 'C:\TestFolder\New Text Document (2).txt' because it is being used by another process. Working, after breaking 

在查看我的代码之后,您将看到上面的打印输出意味着首先抛出了“无法访问文件”exception,但是在catch语句中执行相同的调用突然起作用。

这对我来说没有任何意义,因为该文件显然没有被其他任何东西使用(我刚刚创建它)..并且无论如何它会在一秒后工作….

以下是我的代码

XAML:

   

代码背后:

 using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace WpfApplication1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { test(); } String Folder = @"C:\TestFolder"; private void test() { FileSystemWatcher watch = new FileSystemWatcher(Folder); watch.Created += new FileSystemEventHandler(FileCreated); watch.EnableRaisingEvents = true; Process.Start(Folder); } private void FileCreated(object sender, FileSystemEventArgs fsEvent) { if (File.Exists(fsEvent.FullPath)) { // Thread.Sleep(1000);// Sleeping for 1 second seems to prevent the error from happening...? // If i am debugging, and pause on exceptions... then it also suddenly works (similar to the Sleep above) try { FileStream fs = new FileStream(fsEvent.FullPath, FileMode.Open); Console.WriteLine("Working"); fs.Close(); } catch (IOException ex) { Console.WriteLine("Broken: " + ex.Message); try { FileStream fs = new FileStream(fsEvent.FullPath, FileMode.Open); Console.WriteLine("Working, after breaking"); fs.Close(); } catch(IOException ex2) { FileStream fs = new FileStream(fsEvent.FullPath, FileMode.Open); Console.WriteLine("really broken: " + ex2.Message); fs.Close(); } } } } } } 

我已经看到了自.NET 1.0以来你所描述的行为,并且从未费心去发现它为什么会发生。 看起来操作系统或.NET有时(?)在调用close和dispose后短时间内锁定文件。

我做了一个解决方法 – 或者如果你愿意,那就是黑客攻击 – 这对我们来说已经certificate是非常强大的。 我们每天在服务器场中处理数百万个文件,并且filewatchers检测到的所有文件在传递给进一步处理之前都会通过此方法。

它的作用是在文件上放置一个独占锁。 如果失败,它将可选择等待最多10秒钟,以便在放弃之前关闭文件。

  public static bool IsFileClosed(string filepath, bool wait) { bool fileClosed = false; int retries = 20; const int delay = 500; // Max time spent here = retries*delay milliseconds if (!File.Exists(filepath)) return false; do { try { // Attempts to open then close the file in RW mode, denying other users to place any locks. FileStream fs = File.Open(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); fs.Close(); fileClosed = true; // success } catch (IOException) {} if (!wait) break; retries --; if (!fileClosed) Thread.Sleep( delay ); } while (!fileClosed && retries > 0); return fileClosed; } 

最有可能的是, FileCreated事件正在被引发并尝试在完全写入磁盘之前处理该文件。

请参阅等待文件完全写入以获得一种技术以避免此问题。

尝试禁用任何防病毒/反恶意软件。 大多数配置为默认情况下在创建时扫描文件。