22

I have a simple class XmlFileHelper as follows:

public class XmlFileHelper
{
    #region Private Members

    private XmlDocument xmlDoc = new XmlDocument();
    private string xmlFilePath;

    #endregion

    #region Constructor

    public XmlFileHelper(string xmlFilePath)
    {
        this.xmlFilePath = xmlFilePath;
        xmlDoc.Load(xmlFilePath);
    }

    #endregion

    #region Public Methods

    public XmlNode SelectSingleNode(string xPathQuery)
    {
        return xmlDoc.SelectSingleNode(xPathQuery);
    }

    public string GetAttributeValueByName(XmlNode node, string attributeName)
    {
        return node.Attributes.GetNamedItem(attributeName).Value;
    }

    #endregion

    #region Public Properties

    public string XmlFilePath
    {
        get
        {
            return xmlFilePath;
        }
    }

    #endregion
}

The issue is I am getting the following error on Load:

System.IO.IOException: The process cannot access the file ''C:\CvarUAT\ReportWriterSettings.xml'' **because it is being used by another process**

this occurs when this class is used to by two running instances of a component running in parallel both attempting to load the xml file above, this is legitimate behaviour and required by the application.

I only want to read in the xml off disk once and release any reference to the file on disk and use an in memory representation from that point forward.

I would have assumed Load operates in a readonly fashion and would have no need to lock the file, what is my best way to achieve the desired result and get around this issue?

Thanks

Graviton
  • 81,782
  • 146
  • 424
  • 602
m3ntat
  • 3,635
  • 11
  • 38
  • 50

4 Answers4

38

You can do this

using (Stream s = File.OpenRead(xmlFilePath))
{
    xmlDoc.Load(s);
}

instead of

xmlDoc.Load(xmlFilePath);
João Angelo
  • 56,552
  • 12
  • 145
  • 147
22

it depends on what you need from the file,

If you need it to be threasdsafe you would need to impliment a mutex to lock the loading between instance,

If you dont really need thread safe loading (i.e. the file never changes) you could load it via a filestream then load the XmlDocument from the stream

            FileStream xmlFile = new FileStream(xmlFilePath, FileMode.Open,
FileAccess.Read, FileShare.Read);
            xmlDoc.Load(xmlFile);
Pharabus
  • 6,081
  • 1
  • 26
  • 39
0

If the file isn't too big to read into memory all at once:

xml.Load(new MemoryStream(File.ReadAllBytes(path)));
Richard Ev
  • 52,939
  • 59
  • 191
  • 278
Michael A. McCloskey
  • 2,391
  • 16
  • 19
-2

try:

xml.Load(
       new StreamReader(
           new FileStream(
                  path, 
                  FileMode.Open, 
                  FileAccess.Read, 
                  FileShare.Read)
            )
          );
rene
  • 41,474
  • 78
  • 114
  • 152
JeffreyABecker
  • 2,724
  • 1
  • 25
  • 36