Johan
Johan

Reputation: 35194

Modifying XML from different Tasks simultaneously

I'm trying to run concurrent read- and write operations on an XML file using Tasks. When I use my FileStream solution below, a new XML document gets appended to the current, rather than just the item. Do I need to clear the document before each new insert? Or do I need to look in to an async XML API?

A simplified example:

public static void AddTestElement()
{
    XDocument doc = XDocument.Load(FilePath);
    XElement item = new XElement("item", "text");

    XElement xmlroot = doc.Element("root");
    if (xmlroot != null)
    {
        xmlroot.Add(item);

        //doc.Save(FilePath); <-- this works, but locks the file

        using (FileStream fs = new FileStream(FilePath, 
               FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
        {
            doc.Save(fs);
        }
    }
}

Called using:

Task.Factory.StartNew(AddTestElement);

Before:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <item>text</item>
</root>

After:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <item>text</item>
</root>
<?xml version="1.0" encoding="utf-8"?>
<root>
    <item>text</item>
    <item>text</item>
</root>

Upvotes: 1

Views: 220

Answers (2)

Srikanth
Srikanth

Reputation: 1010

Append: Opens the file if it exists and seeks to the end of the file, or creates a new file.
Create: Specifies that the operating system should create a new file. If the file already exists, it will be overwritten.

In this it will overwrite your file content

CreateNew : Specifies that the operating system should create a new file. Try the following solution

 static void Main(string[] args)
{
    ProcessWrite().Wait();
    Console.Write("Done ");
    Console.ReadKey();
}

static Task ProcessWrite()
{
    string filePath = @"C:\Users\Srikanth\Desktop\sample.xml";

    return WriteTextAsync(filePath);
}

static async Task WriteTextAsync(string FilePath)
{
    XDocument doc = XDocument.Load(FilePath);
    XElement item = new XElement("item", "text");

    XElement xmlroot = doc.Element("root");


    if (xmlroot != null)
    {
        xmlroot.Add(item);
        //doc.Save(FilePath); <-- this works, but locks the file

        using (FileStream fs = new FileStream(FilePath,
               FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
        {
            doc.Save(fs);
        }
    }

}

Upvotes: 2

Alireza
Alireza

Reputation: 5056

It has nothing to do with the Task. It is because you have passed FileMode.Append to FileStream's constructoe. Just use FileMode.Create and you will be fine.

Upvotes: 1

Related Questions