10
votes

I have a program that roughly does this:

  1. open a file to read from it.
  2. close the file
  3. Start a filewatcher to watch for changes in the file.
  4. As soon as a change is detected, the filewatcher's EnableRaisingEvents flag is set to false and the process repeats from Step 1.

The problem is, after going from step 4 to step 1, it cannot read the file saying that it is being used by another Process.

Error I receive:

Unhandled Exception: System.IO.IOException: The process cannot access the file 'c:\test.xml' because it is being used by another process.

Whats going wrong? does the reader from Step 1 of my program still have the file open, or is some entirely different process accessing the file, or is it that filewatcher is still watching the file after moving to Step 1 from 4, despite setting the flag to false?

7
Can you post your code. That may help us answer your question. - Kevin LaBranche
Post some code. Help us help you. - Bob G
The code is kinda huge and confidential since it is for a financial firm, but i'll see if i can make it safe and post it. - xbonez
Maybe you should post some code (just the parts that open and close the file). Maybe your program still has the file open, or maybe FileWatcher does. - JohnB
it is very likely that your code from step 1 is keeping the file locked, I would look there first - BlackTigerX

7 Answers

9
votes

If your code is similar to this:

[STAThread]
static void Main(string[] args)
{
    string file = "temp.txt";
    ReadFile(file);
    FileSystemWatcher fswatcher = new FileSystemWatcher(".\\");
    fswatcher.Changed += delegate(object sender, FileSystemEventArgs e)
                             {
                                 ReadFile(e.FullPath);
                             };
    while (true)
    {
        fswatcher.WaitForChanged(WatcherChangeTypes.Changed);
    }
}
private static void ReadFile(string file)
{
    Stream stream = File.OpenRead(file);
    StreamReader streamReader = new StreamReader(stream);
    string str = streamReader.ReadToEnd();
    MessageBox.Show(str);
    streamReader.Close();
    stream.Close();
}

If you are editing the file via notepad, then, when you click the save button, it keeps the file open, while as if when you just close the program and click save it doesn't. I do no know if this is a bug or an undocumented feature of notepad, but this just might be your problem. One way to fix this is to do the following:

In your anonymous delegate, or wherever you execute the call to ReadFile() call Thread.Sleep(1000), to have the program wait before reading the file and your code should work fine.

4
votes

You can use a tool like Process Explorer from http://www.sysinternals.com to see who has the open handle to the process

The file is most likely held open by whatever caused the change notification to fire in the first place.

3
votes

Beside other answers it is possible that when FileWatcher reacts file it not yet closed by that app. In step 1 try not to fail immediately but try several attempts with small delay.

3
votes

Note: even if "file.txt" is open in Notepad, this code still works, because it is opening for read.

using System;
using System.IO;

class Program
{
  static void Main(string[] args)
  {
    ReadFromFile(@"C:\file.txt");
    Console.ReadLine();
  }

  static void ReadFromFile(string filename)
  {
    string line;
    using (StreamReader sr = File.OpenText(filename))
    {
      line  = sr.ReadLine();
      while (line != null)
      {
        Console.WriteLine(str);
        line = sr.ReadLine();
      }
      sr.Close();
    }
  }
}

Or just:

string text = System.IO.File.ReadAllText(@"C:\file.txt");

1
votes

The problem is that the FileSystemWatcher tells you immediately when the file was created. It doesn't wait for the file to be released. For instance, when you copy a large file which takes 3 seconds to copy, so you have to open the file after that.

http://www.codeproject.com/Questions/461666/FileSystemWatcher-issue-in-windows-application Wait until file is unlocked in .NET

0
votes

There are a number of things that could be going on.

First, make sure you properly dispose of the file writer (close isn't good enough) by utilizing the using clause around everything that implements IDisposable.

Second, it you are simply reading, make sure you have the correct flags set when opening the file.

To go any further it would help if you provided a code block which showed how you were accomplishing this; particularly around the reading of the file

0
votes

You can use this MS utility openfiles to obtain list of opened files and understand who has opened the file.

openfiles /query

Also it allow to disconnect files opened by network users.

openfiles /disconnect /id XXXX

If you want use it for local PC you should set Maintain Objects List global flag:

openfiles /local on

Follow the link to get more details.