6

I have this problem in my application:

  • Step 1 - create an file (xml) and put some content in it
  • Step 2 - a 3rd party application will open the file and get the info from the file made in step 1.
  • Step 3 - delete the file again.

The first question that I have is about this part of the code:

XmlDocument xmlDoc = new XmlDocument();
DataSet ds = //use a method to put in the data
xmlDoc.LoadXml(ds.GetXml());
xmlDoc.Save("Filename");
// ...
Process.Start(startInfo);

Is my assumption correct that the last line only gets executed when the above is already done? So I can be 100% sure that the data is all in the xml before it tries to start it right?

The second part where I get an error now is here:

Process.Start(startInfo);
File.Delete("Filename");

What happens now, is that the file already gets deleted before the 3rd party program had read it into its memory.

Is there some way that I can check that the file is no longer in use, or make some stable way of waiting?

I already found a way to use Thread.Sleep(TimeInMiliSec); but I guess this is not a correct way of doing this (more like a workaround solution)?

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Dante1986
  • 58,291
  • 13
  • 39
  • 54

4 Answers4

10

Description

You can use the method in my sample and do a while loop.

Sample

while (IsFileLocked(new FileInfo("YourFilePath")))
{
    // do something, for example wait a second
    Thread.Sleep(TimeSpan.FromSeconds(1));
}
// file is not locked

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

    try
    {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
        return true;
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }
    return false;
}
Community
  • 1
  • 1
dknaack
  • 60,192
  • 27
  • 155
  • 202
  • This is addressing the subject alone, not the fact that the code posted is accessing the same file from two processes rather than waiting for the process to end. – Servy Jan 25 '12 at 21:57
  • This will wait as long the file can be deleted – dknaack Jan 25 '12 at 21:59
  • Just be careful with catching IOException with this code. If the file does not exist you could be stuck in a loop due to the fact that FileNotFoundException extends IOException. – gregwhitaker Jan 25 '12 at 22:14
  • is my assumption correct that the last line only gets executed when the above is already done ? so the start will only occur once the save is done ? – Dante1986 Jan 25 '12 at 22:15
  • @Dante1986 - Yes, XmlDocument.Save is a synchronous call. It will save the file before returning and executing your Process.Start. – gregwhitaker Jan 25 '12 at 22:17
  • @Dante1986 The last line after the `while` loop occurs only if the file is not locked, yes – dknaack Jan 25 '12 at 22:19
  • This man is a god. His code works perfectly. – WyattH7 Apr 18 '23 at 05:15
4

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.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • in case of a crash on the 3rd party program, will it also count as an exit ? because i can't really know what the user does in third 3rd party program, or how he exits there – Dante1986 Jan 25 '12 at 21:56
  • @Dante1986 If the other process crashes WaitForExit will return, yes. If there are other programs touching the file then you'll be forced to use one of the other answers, but if you are only tripping over yourself then you should be doing something like this. – Servy Jan 25 '12 at 21:58
3
Process process = Process.Start(startInfo);
process.WaitForExit(); // alteratively, you can use WaitForExit(int milliseconds)
File.Delete("Filename");  
Phil Bolduc
  • 1,586
  • 1
  • 11
  • 19
2

This is a common problem. The solution is unfortunatley try to open it and see if there's an exception.

Use the IsFileLocked(...) from here:

Is there a way to check if a file is in use?

And do something like:

while ( IsFileLocked(new FileInfo(FilePath)) ) 
{ 
    Thread.Sleep(TimeInMiliSec); 
}
Community
  • 1
  • 1
DanTheMan
  • 3,277
  • 2
  • 21
  • 40