Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait until file is unlocked in .NET

What's the simplest way of blocking a thread until a file has been unlocked and is accessible for reading and renaming? For example, is there a WaitOnFile() somewhere in the .NET Framework?

I have a service that uses a FileSystemWatcher to look for files that are to be transmitted to an FTP site, but the file created event fires before the other process has finished writing the file.

The ideal solution would have a timeout period so the thread doesn't hang forever before giving up.

Edit: After trying out some of the solutions below, I ended up changing the system so that all files wrote to Path.GetTempFileName(), then performed a File.Move() to the final location. As soon as the FileSystemWatcher event fired, the file was already complete.

like image 270
Chris Wenham Avatar asked Sep 08 '08 21:09

Chris Wenham


2 Answers

Starting from Eric's answer, I included some improvements to make the code far more compact and reusable. Hope it's useful.

FileStream WaitForFile (string fullPath, FileMode mode, FileAccess access, FileShare share) {     for (int numTries = 0; numTries < 10; numTries++) {         FileStream fs = null;         try {             fs = new FileStream (fullPath, mode, access, share);             return fs;         }         catch (IOException) {             if (fs != null) {                 fs.Dispose ();             }             Thread.Sleep (50);         }     }      return null; } 
like image 56
mafu Avatar answered Oct 12 '22 17:10

mafu


This was the answer I gave on a related question:

    /// <summary>     /// Blocks until the file is not locked any more.     /// </summary>     /// <param name="fullPath"></param>     bool WaitForFile(string fullPath)     {         int numTries = 0;         while (true)         {             ++numTries;             try             {                 // Attempt to open the file exclusively.                 using (FileStream fs = new FileStream(fullPath,                     FileMode.Open, FileAccess.ReadWrite,                      FileShare.None, 100))                 {                     fs.ReadByte();                      // If we got this far the file is ready                     break;                 }             }             catch (Exception ex)             {                 Log.LogWarning(                    "WaitForFile {0} failed to get an exclusive lock: {1}",                      fullPath, ex.ToString());                  if (numTries > 10)                 {                     Log.LogWarning(                         "WaitForFile {0} giving up after 10 tries",                          fullPath);                     return false;                 }                  // Wait for the lock to be released                 System.Threading.Thread.Sleep(500);             }         }          Log.LogTrace("WaitForFile {0} returning true after {1} tries",             fullPath, numTries);         return true;     } 
like image 38
Eric Z Beard Avatar answered Oct 12 '22 16:10

Eric Z Beard