Search code examples
c#.netxmlread-writefile-access

Reading an XML file while it is being written to


I have a long-running REST API method which compiles an XML file. The user makes a request to initiate this compilation, the basic file is created, and the user is then given a unique ID with which to query for progress.

When called, the progress-reading method opens the file with read-only access, instantiates an XDocument object and counts the number of elements therein.

The code which populates the XML file is accessed with

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
    var xmlDoc = XDocument.Load(fs);

    foreach (...)
    {
        // add the element to xmlDoc

        xmlDoc.Save(filePath);
    }
}

And the code which reads the file in order to count the number of elements

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    var xmlDoc = XDocument.Load(fs);

    // count elements
}

However, in the populating method an exception is thrown on xmlDoc.Save(filePath);

The process cannot access the file '...' because it is being used by another process.

As I understood it, opening the FileStream with FileShare.Read allows another process to open the file with read-only access (and I believe this is happening) and likewise using FileShare.ReadWrite in the reading/counting method would permit the populating process to open the file with write-access.

Why doesn't the above code allow both processes to do what I expect?


Solution

  • When you call

    xmlDoc.Save(filePath)
    

    you pass filename, so XmlDocument does not use your fs stream you opened for writing. Instead it opens yet another stream internally, which of course fails because you already have one stream opened for writing.

    Instead, seek to the beginning of the stream and then call

    xmlDoc.Save(fs);
    

    You may also set stream length to zero before saving (to truncate old contents), though not completely sure irs necessary.