-1

I have recently started working with FileSystemWatcher. I have a requirement to monitor a certain directory and any new files added to that directory get MD5 checksum and display it in the console. So I've added the appropriate event handler

watcher.Created += new FileSystemEventHandler(OnCreated);

Then the OnCreated looks like

private static void OnCreated(object sender, FileSystemEventArgs e)
  {
      using (var md5 = MD5.Create())
      {
          using (var stream = File.OpenRead("C:\\Test\\Uploads\\"+ e.Name))
          {
              byte[] checkSum = md5.ComputeHash(stream);

              StringBuilder sb = new StringBuilder();
              for (int i = 0; i < checkSum.Length; i++)
              {
                  sb.Append(checkSum[i].ToString());
              }

              Console.WriteLine(sb.ToString());
          }
      }
  }

This works perfectly fine when the first file is created however as soon as another file is created in the directory I get the following error

Additional information: The process cannot access the file 'C:\Test\Uploads\New Text Document (2).txt' because it is being used by another process

The line which is throwing the error is

using (var stream = File.OpenRead("C:\\Test\\Uploads\\"+ e.Name))

I've also tried stream.Dispose(); but have the same issue. Does anyone know where I'm going wrong? Thanks in advance for all your help and support.

silent
  • 14,494
  • 4
  • 46
  • 86
Izzy
  • 6,740
  • 7
  • 40
  • 84
  • 3
    maybe it is is being used by *another* process - perhaps the file is not done being created/written to? – Ňɏssa Pøngjǣrdenlarp Feb 03 '15 at 14:54
  • does e.Name always contain the name of the newly created file? – silent Feb 03 '15 at 15:01
  • @silent Yes, It always has the name of the newly created file – Izzy Feb 03 '15 at 15:02
  • hm, have you tried to insert a sleep of a few seconds before trying to open the file? maybe your event handler is triggered and the file is not completely created yet – silent Feb 03 '15 at 15:03
  • @silent I've tried `Thread.Sleep(5000);` still get the same issue – Izzy Feb 03 '15 at 15:04
  • How do you create your files? Is the folder empty, when this works for the first file? – silent Feb 03 '15 at 15:06
  • @silent Yes, when the first file is created the folder is empty – Izzy Feb 03 '15 at 15:06
  • @Downvoter care to explain why? – Izzy Feb 03 '15 at 15:07
  • Is a large file being copied? Which process copies the file to that folder? Do you know the sharing permission between processes that you have? – dariogriffo Feb 03 '15 at 15:07
  • Look at this, probably is not a solution, but could help. [http://stackoverflow.com/questions/11072295/which-filter-of-filesystemwatcher-do-i-need-to-use-for-finding-new-files][1] [1]: http://stackoverflow.com/questions/11072295/which-filter-of-filesystemwatcher-do-i-need-to-use-for-finding-new-files – Damianos88 Feb 03 '15 at 15:08
  • @dariogriffo The files at the moment are no larger than 20KB. For now the files are manually being added to the directory – Izzy Feb 03 '15 at 15:09
  • @Damianos88 I have all 3 of those filters already in place – Izzy Feb 03 '15 at 15:10
  • I tried your function and effectively throws an exception. The only way I didn't get the excepetion is putting a Thread.Sleep(1000); before the using (var md5 = MD5.Create()) Hope it helps – dariogriffo Feb 03 '15 at 15:21
  • 2
    @dariogriffo Thanks for the info but I would prefer to use it without `Thread.Sleep(1000)` You can refer to **[this](http://stackoverflow.com/a/8815944)** answer for my reasons – Izzy Feb 03 '15 at 15:44
  • Then why don't you implement a time out? As long as the file cannot be opened retry X times and sleep 1000 ms in between. – silent Feb 03 '15 at 16:09
  • I understand what you say, I was just trying to find a loophole, and that is why is a comment, not an answer :D – dariogriffo Feb 03 '15 at 16:16
  • I can make it an answer if you like ;-) – silent Feb 03 '15 at 16:36
  • @silent If you can make an answer with a short example that would be highly appreciated – Izzy Feb 03 '15 at 16:48

1 Answers1

2

As discussed above, try this simple time out with retries

        using (var md5 = MD5.Create())
        {
            int retries = 10;
            while (retries > 0)
            {
                try
                {
                    using (var stream = File.OpenRead("C:\\Test\\Uploads\\" + e.Name))
                    {
                        byte[] checkSum = md5.ComputeHash(stream);

                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < checkSum.Length; i++)
                        {
                            sb.Append(checkSum[i].ToString());
                        }
                    }
                    // All done, leave the loop
                    break;
                }
                catch (FileNotFoundException e)
                {
                    // Check for your specific exception here
                    retries--;
                    Thread.Sleep(1000);
                }
            }
            // Do some error handling if retries is 0 here
        }

Note that in the Catch block you have to properly check for your specific error. In any other case you want to handle the exception.

silent
  • 14,494
  • 4
  • 46
  • 86