Wait for File to Be Freed by Process

Wait for file to be freed by process

A function like this will do it:

public static bool IsFileReady(string filename)
{
// If the file can be opened for exclusive access it means that the file
// is no longer locked by another process.
try
{
using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
return inputStream.Length > 0;
}
catch (Exception)
{
return false;
}
}

Stick it in a while loop and you have something which will block until the file is accessible:

public static void WaitForFile(string filename)
{
//This will lock the execution until the file is ready
//TODO: Add some logic to make it async and cancelable
while (!IsFileReady(filename)) { }
}

Check if a file is in use, wait for it to finish

It looks like you just need to add something like the following:

Process p = new Process();
p.StartInfo = startInfo;
p.WaitForExit();

Process.Start() starts another process but it doesn't wait for that process to finish before continuing on.

Wait Until File Is Completely Written

There is only workaround for the issue you are facing.

Check whether file id in process before starting the process of copy. You can call the following function until you get the False value.

1st Method, copied directly from this answer:

private bool IsFileLocked(FileInfo file)
{
FileStream stream = null;

try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}

//file is not locked
return false;
}

2nd Method:

const int ERROR_SHARING_VIOLATION = 32;
const int ERROR_LOCK_VIOLATION = 33;
private bool IsFileLocked(string file)
{
//check that problem is not in destination file
if (File.Exists(file) == true)
{
FileStream stream = null;
try
{
stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (Exception ex2)
{
//_log.WriteLog(ex2, "Error in checking whether file is locked " + file);
int errorCode = Marshal.GetHRForException(ex2) & ((1 << 16) - 1);
if ((ex2 is IOException) && (errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION))
{
return true;
}
}
finally
{
if (stream != null)
stream.Close();
}
}
return false;
}

IOException happening despite thread synchronization C#

There are a few things that you are missing here:

  1. The event that you are hooking is FileCreated. This event is fired (probably unsurprisingly) when the file is created by some other process, not when that other process has finished writing the file. What's happening here is that your process is getting notified while the other process is still writing the file, and has an exclusive lock on it. From the documentation:

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.


  1. After the file is created, you loop over all of the files in the directory (not just the file that was just created) and transport all of them. If multiple files are created, the first call to the event will attempt to access any files in the directory (in parallel, in fact), and so even if 1) wasn't an issue, you could have a collision here with another file being written to while processing the event for the first.

The right thing to do here is to loop until you are able to read the file, as specified in the second answer here: Wait for file to be freed by process



Related Topics



Leave a reply



Submit