0

I am calling below method in a loop with same xmlRequestPath and xmlResponsePath files. Two loop counts it executes fine in the 3rd iteration I am getting exception "The process cannot access the file because it is being used by another process.".

    public static void UpdateBatchID(String xmlRequestPath, String xmlResponsePath)
    {
        String batchId = "";
        XDocument requestDoc = null;
        XDocument responseDoc = null;
        lock (locker)
        {
            using (var sr = new StreamReader(xmlRequestPath))
            {
                requestDoc = XDocument.Load(sr);
                var element = requestDoc.Root;
                batchId = element.Attribute("BatchID").Value;

                if (batchId.Length >= 16)
                {
                    batchId = batchId.Remove(0, 16).Insert(0, DateTime.Now.ToString("yyyyMMddHHmmssff"));
                }
                else if (batchId != "") { batchId = DateTime.Now.ToString("yyyyMMddHHmmssff"); }
                element.SetAttributeValue("BatchID", batchId);
            }

            using (var sw = new StreamWriter(xmlRequestPath))
            {
                requestDoc.Save(sw);
            }

            using (var sr = new StreamReader(xmlResponsePath))
            {
                responseDoc = XDocument.Load(sr);
                var elementResponse = responseDoc.Root;
                elementResponse.SetAttributeValue("BatchID", batchId);

            }

            using (var sw = new StreamWriter(xmlResponsePath))
            {                    
                responseDoc.Save(sw);                    
            }
        }
        Thread.Sleep(500);

        requestDoc = null;
        responseDoc = null;
    }

Exception is occurring at using (var sw = new StreamWriter(xmlResponsePath)) in above code.

Exception:

The process cannot access the file 'D:\Projects\ESELServer20130902\trunk\Testing\ESL Server Testing\ESLServerTesting\ESLServerTesting\TestData\Assign\Expected Response\Assign5kMACResponse.xml' because it is being used by another process.

Rohit
  • 10,056
  • 7
  • 50
  • 82
Anup
  • 39
  • 11
  • Why is your responseDoc.Save(sw); creating a new instance of sw? Shouldn't it be in the same using section where you are loading it and setting the attribute? – Dijkgraaf Nov 06 '13 at 06:24
  • Hi Dijkgraaf, I am creating StreamReader instance to read the XML. When I am done with setting the attribute I want to save it in same XML file. So I am creating another StreamWriter instance to save in same XML file from which I have read earlier. – Anup Nov 06 '13 at 07:06
  • Is there another part of your code (after the call to the `UpdateBatchID` method) that uses the XML files? – Andrei V Nov 06 '13 at 07:49
  • I think you need to close you read stream, before you can open the same file for writing. – Dijkgraaf Nov 06 '13 at 08:02
  • Hi Andrei, Yes, I am loading the xml file in an object from another thread. But file access is Read. is this causing the problem. serializer = new XmlSerializer(typeof(Response)); loadStream = new FileStream(inputFileName, FileMode.Open, FileAccess.Read); Response loadedResponseObject = (Response)serializer.Deserialize(loadStream); return loadedResponseObject; – Anup Nov 06 '13 at 08:06
  • @Dijkgraaf, there's no need to explicitly close the streams. The `Using` statement [does that automatically](http://stackoverflow.com/questions/4136490/do-i-need-to-explicitly-close-the-streamreader-in-c-sharp-when-using-it-to-load). – Andrei V Nov 06 '13 at 08:19
  • Anup, it's a bit hard for me to see from the provided code if the file is still open. Jugging from the exception, it's probably so. As far as I see, in the other thread you don't close the `FileStream` after loading. Try adding `loadStream.Close()` before the `return`. – Andrei V Nov 06 '13 at 08:23
  • Thanks Andrei, I closed the stream in another thread. That solved the problem. – Anup Nov 06 '13 at 08:53
  • No problem. Glad I could help. If you're new to this, remember that all streams must be explicitly closed, unless you're opening them within the `Using` statement. – Andrei V Nov 06 '13 at 08:56

2 Answers2

0

Maybe at the third loop the stream is still being closed, so it tells you that it is non accessible. Try waiting a bit before calling it again in the loop, for example:

while (...)
{
    UpdateBatchID(xmlRequestPath, xmlResponsePath);
    System.Threading.Thread.Sleep(500);
}

Or, close explicitly the stream instead of leaving the work to the garbage collector:

var sr = new StreamReader(xmlResponsePath);
responseDoc = XDocument.Load(sr);
     ....
sr.Close();
Alex
  • 6,849
  • 6
  • 19
  • 36
0

Instead of using two streams, a Write and a Read stream, try using only a FileStream, since the problem might be that after loading the file the stream remains opened until the garbadge collector actives.

using (FileSteam f = new FileStream(xmlResponsePath))
{
     responseDoc = XDocument.Load(sr);

     var elementResponse = responseDoc.Root;
     elementResponse.SetAttributeValue("BatchID", batchId);

     responseDoc.Save(sw);                    
}
Alex
  • 6,849
  • 6
  • 19
  • 36