1

I have a C# utility that needs perform some actions as soon as a specific file is released by another process, i.e. that process stops writing into the file. I am using the code below but it's behaving inconsistently on a Windows 7 system.

private static bool FileWritten(string filename)
    {
        try
        {
            using (FileStream inputStream = File.Open(filename, FileMode.Open,
                        FileAccess.Read,
                        FileShare.None))
            {
                return true;
            }
        }
        catch (IOException e)
        {
            return false;
        }
    }

Sometimes it would return false even though it seems that the file has already been released. I am calling FileWritten() in a while(true) loop that keeps checking calling FileWritten() as long as it returns false, and then exits after some max time. Debugging this is difficult since it seems to work fine under debugger (i.e. it returns true as soon as the file is actually released) but then does not work when I launch my code directly. Also, even adding debug prints seems to affect its behavior.

Is there a more reliable way to check if a file has been written to and released, that would work Win 7 and, preferably, also on Win XP?

I Z
  • 5,719
  • 19
  • 53
  • 100

2 Answers2

1

There is no perfect solution for this problem.

Even if your code was working fine on Windows 7, there would still be race conditions.

Imagine FileWritten returns false at a certain point in time. Your code assumes the file is not locked anymore and continue its execution... but the file could be locked again the next millisecond and the next time you try to access to the file it'll throw an exception...

Can't you just try to access to your file, and catch the exception if you can't access to it? You could then wait a few amount of time then try again. It would be cleaner IMO than a function that tries to returns a boolean indicating if the file is used by a process or not.

ken2k
  • 48,145
  • 10
  • 116
  • 176
0

You could use FileSystemWatcher to listen for events on the file. A few of the options will allow you to see if the file has been changed. You can sleep your thread for a certain amount of time, using a popcorn effect (resetting the timer) whenever you receive a notification that the file changed. Then execute your code (but actually have it do your work in the True path while you have the lock). If the file is still locked, you'll get false, sleep some more waiting for events.

Other than having the other process rename/copy the original file to a new location when it's done, there's no universal API that will give you the file lock immediately after another process drops it. (That I know of).

Michael Brown
  • 9,041
  • 1
  • 28
  • 37