3

Hoping I might be able to get some help with an infuriating problem which I can't seem to find a definitive answer for anywhere.

I am appending data to an xml document using an XDocument object, and then overwriting the existing file using xDoc.save(path), but for some reason the first time I run the code an error is thrown even though the file is not in use by any other process.

*"The process cannot access the file "C:\XXX\XXXX\Telemetry\2011_11_22.tlm because it is being used by another process."*

Subsequent iterations do not cause a problem.

Here is my code that I am using with try/catch removed for readability:-

XElement x = GenerateTelemetryNode(h); //Create a new element to append

            if (File.Exists(path))
            {
                if (xDoc == null)
                {
                    xDoc = XDocument.Load(new StreamReader(path));
                }
            }
            else
            {
                xDoc = new XDocument();
                xDoc.Add(new XElement("TSD"));
            }
            xDoc.Element("TSD").Add(x);
            xmlPath = path;
            xDoc.Save(path);

I'm sure there's a very simple explanation for it.

Many thanks in advance for any replies.

davidpcl1977
  • 111
  • 2
  • 9

4 Answers4

5

I would expect the problem is the StreamReader hasn't been disposed in which case it will still be attached to the document. I would suggest using wrapping the StreamReader creation in a using clause to ensure that is disposed of immediately after the document has been loaded:

 if (xDoc == null)
 {
        using (var sr = new StreamReader(path))
        {        
           xDoc = XDocument.Load(new StreamReader(sr));
        }
 }
Andy Rose
  • 16,770
  • 7
  • 43
  • 49
  • That's fixed my problem - thankyou very much. I will have to read up on the Using keyword - Have a lot of programming experience, but am only just starting to get fully to grips with a lot of concepts in C#. Nice Pearl Jam logo by the way - been a massive fan since they started out - and finally got to see them live a few years ago. Dave – davidpcl1977 Nov 22 '11 at 14:06
  • @davidpcl1977 - glad it helped. It's well worth get to grips with the using keyword as it's a very elegant way of handling disposible objects. Looking forward to watching Pearl Jam 20 and reliving my youth. ;-) – Andy Rose Nov 22 '11 at 14:40
  • 5
    in Andy's code, sr is already a Stream, so the xDoc assignment statement doesn't need to invoke the StreamReader copy constructor. It should be: xDoc = XDocument.Load(sr); – sscheider Jan 18 '14 at 16:48
1

Use the overload of XDocument.Load that takes a Uri (the file name) and not a stream.

Polyfun
  • 9,479
  • 4
  • 31
  • 39
1
        if (File.Exists(path))
        {
            if (xDoc == null)
            {
                StreamReader stream = new StreamReader(path);
                using (stream)
                {
                    xDoc = XDocument.Load(stream);
                }
            }
        }
        else
        {
            xDoc = new XDocument();
            xDoc.Add(new XElement("TSD"));
        }
        xDoc.Element("TSD").Add(x);
        xmlPath = path;
        xDoc.Save(path);
Azhar Khorasany
  • 2,712
  • 16
  • 20
0

Can't test for the moment, but I'd suspect the StreamReader to be using it, especially if you first iteration only causes this Exception. Have you tried :

XElement x = GenerateTelemetryNode(h); //Create a new element to append

        if (File.Exists(path))
        {
            if (xDoc == null)
            {
                StreamReader reader = new StreamReader(path);
                xDoc = XDocument.Load(reader);
                reader.Close();
                reader.Dispose();
            }
        }
        else
        {
            xDoc = new XDocument();
            xDoc.Add(new XElement("TSD"));
        }
        xDoc.Element("TSD").Add(x);
        xmlPath = path;
        xDoc.Save(path);
psycho
  • 631
  • 10
  • 27