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.
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; }
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; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With