Search code examples
c#file-watcher

FileSystemWatcher - unable to read created file


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.


Solution

  • 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.