2

Why do i get an IOException (The process cannot access the file because it is being used by another process.), when i copy the same file 3 Times into Folder A?

class FileWatcher {

    FileSystemWatcher fsw;
    FileInfo file;
    string destination = @"C:\FileMover\B\";
    Random random;

    public FileWatcher() {
        fsw = new FileSystemWatcher();
        random = new Random();           

        fsw.Path = @"C:\FileMover\A";

        fsw.Created += fsw_Created;

        fsw.EnableRaisingEvents = true;
    }

    void fsw_Created(object sender, FileSystemEventArgs e) {            
        string destinationFileName = destination + e.Name;

        if (!File.Exists(destinationFileName)) {
            file = new FileInfo(e.FullPath);
            file.MoveTo(destinationFileName);
        }
        else {
            file = new FileInfo(e.FullPath);                
            file.MoveTo(destinationFileName + random.Next());
        }
        file = null;                       
    }  
}

Main:

class Program {      
    static void Main(string[] args) {

        FileWatcher watcher = new FileWatcher();

        while (Console.ReadKey().Key != ConsoleKey.Q) {

        }
    }
}

After 2 times folder B contains 2 files (sourceFileName and sourceFileName1274968236)

When i debug the section no Exception will be thrown.

VSDekar
  • 1,741
  • 2
  • 21
  • 36
  • I can't replicate this - I can paste the file any number of times and no exceptions are thrown. Do you get the exception every time? What platform are you running on? – Steve Ruble Aug 21 '14 at 20:36
  • Yes i get the exception every time. I'm running a Windows 8.1 pro. And when i close my programm and restart it, i will get the Exception immediately after i copy the same file into folder A. – VSDekar Aug 22 '14 at 04:34

2 Answers2

3

Created might be raised before the file is flushed (?) into the destination. Try using Changed and check for e.ChangeType==WatcherChangeTypes.Created.

ref: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created(v=vs.110).aspx

Edit: The Changed event is raised after Created, if this is due to a race-condition, probably will help but problem may still happen.

The OnCreated event is raised as soon as a file is created. If a file is being copied or transferred into a watched directory, the OnCreated event will be raised immediately, followed by one or more OnChanged events.

Found this: Wait Until File Is Completely Written and this: Is there a way to check if a file is in use?

Community
  • 1
  • 1
celerno
  • 1,367
  • 11
  • 30
  • The accepted answer in [Wait Until File Is Completely Written](http://stackoverflow.com/questions/10982104/wait-until-file-is-completely-written) helped me. I'll do some more tests and then mark this as answer. Also thanks to LaMMMy – VSDekar Aug 22 '14 at 04:57
  • Everything works fine now. Most important hint was to use the Changed Event instead of Created. – VSDekar Aug 22 '14 at 07:18
1

Using tips from @celerno and the links he shared, here is what I found to work:

    public FileWatcher()
    {
        fsw = new FileSystemWatcher();
        random = new Random();

        fsw.Path = @"C:\FileMover\A";

        fsw.Created += fsw_Created;
        fsw.Changed += fsw_Created;

        fsw.EnableRaisingEvents = true;
    }

and change the fsw_Created to:

        if(!IsFileLocked(fi)){
            if (!File.Exists(destinationFileName))
            {
                fi = new FileInfo(e.FullPath);
                fi.MoveTo(destinationFileName);
            }
            else
            {
                fi = new FileInfo(e.FullPath);
                string fileName = destinationFileName + random.Next();
                fi.MoveTo(fileName);
            }
            fi = null;
        }

Where IsFileLocked is directly taken from the link that was mentioned by @celerno.

I dropped many many copies of the file and it never threw an exception. I'm guessing an Changed event happens right after the file gets released, otherwise, if it is locked at the time of the attempted move, the Created never gets called, so the file just sits there. It appears you need both in this situation.

I just wanted to edit in order to add that the exception seemed to only get thrown when you're copying a file of the same name over and over into the source directory. Guessing the lock on that filename just needs to be released before you can copy another with the same name.

Community
  • 1
  • 1
Bensonius
  • 1,501
  • 1
  • 15
  • 39
  • Race conditions are usually difficult or impossible to reproduce exactly from one computer to another, thats why i didn't bother into reproduce the problem. Also, the helper IsFileLocked, isn't 100% safe, see this comment: http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use#comment2966182_937558 – celerno Aug 21 '14 at 20:53
  • I did see that comment. I realize the race condition is not predictable, however I was able to reproduce it and assuming nothing else is using the file this solution is usable. Safeguards would have to be put in place to make sure other sources of file-locking are covered I guess. – Bensonius Aug 21 '14 at 21:02