1

I have this open-source library that I'm having some trouble fixing a problem... This library allows to easily create an XML file to store application settings. But I'm having an issue saving the changes.

I have another application where I'm using this library and every time that application window is done resizing, I call the Save() method of the library to save the window size/position to the XML file.

Most of times it works fine, everything is saved. Once in a while though, I get an exception saying the file is being used by another process.

I really need to make sure that changes are saved every time the Save() method is called, I need to handle this exception somehow or prevent it from happening.

What are you guys suggestions for best handling this situation?

The code for the Save() method is the following:

public void Save() {
    // Create a new XML file if there's no root element
    if(xDocument.DocumentElement == null) {
        xDocument = new XmlDocument();
        xDocument.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
            "<" + XmlRootElement + ">\n</" + XmlRootElement + ">");
    }

    // OMITTED CODE WAS HERE (NOT IMPORTANT FOR THE PROBLEM)

    // Create a new XML writer for the XML file
    XmlWriter xWriter = XmlWriter.Create(XmlFilePath, new XmlWriterSettings() {
        Indent = true,
        IndentChars = "\t"
    });

    // Sort the XML file using the XSL sylesheet and save it
    xslTransform.Transform(xDocument, xWriter);

    // Clear the buffer and close the XML writer stream
    xWriter.Flush();
    xWriter.Close();
}
2
  • I see that you accepted the answer of putting the lock statement in and that is cool, but I would caution you to still use the using statement in your code. It will ensure that you always clean up your resources as expected. If you have an exception you will not close the file correctly and may still have contention on the file because the lock will not help. Commented May 11, 2009 at 22:07
  • I'm using it too, thanks for caring. I accepted that answer because it fixed the problem on this question. I no longer have the exception I was having and never had any different ones (not saying I won't have in the future), so the problem is fixed. Still, your additional info is good and that's why I voted for "helpful answer" :) Commented May 12, 2009 at 0:46

4 Answers 4

3

XmlWriter is IDisposable. You should wrap it in a using() clause. http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx

Sign up to request clarification or add additional context in comments.

2 Comments

Can you explain why your almost certain I should use using() instead of lock()? So far, I understand the reasons for the lock and I think it makes sense, not for the using though...
Whoops; I may have misspoken. The using() clause is imperative for a class that implements IDisposable. The lock may also be necessary depending on whether your resize logic allows interleaved or concurrent resize events.
2

I have to go with a combination of the answers already given here.

Your XmlWriter should be in a using block for several reasons. You should dispose it so that your resources are freed as soon as possible. Also, what if you throw an exception while interacting with it. The file wouldn't be closed properly, at least until the finalizer kicks in and frees your resources.

Even with the using statement, you "might" have contention on the file and need to place the Save code in a lock statement. The method is non-reentrant by nature because the file is a shared resource. Putting a lock around it might be over kill if you don't have multiple threads, but you would ensure that you properly controlled access to the file.

The other thing to consider is that you might want to move the saving operation to a background thread to write the file out. If you get a large settings file you might cause strange UI interactions because you are waiting on the file to write every time the user resizes and this happens on the UI thread. If you did this you would definitely need to lock access to the file resource.

Comments

1

It could be the case that the window-resizing-completed events are firing so quickly, that the save function is being called, the called again before it finishes running the first time. This would result in the error you're describing (the other process using the file is... YOU!). Try surrounding your code with a lock, thusly:

lock(some_shared_object)
{
    //Your code here
}

Comments

1

Also you might try using a lock statement. It could be that the methods are overrunning one another.

2 Comments

It's 99.44% certain it is the using() statement. You don't need a lock.
I'm not certain the using() is the root problem, since he has a call to XmlWriter.Close(). I don't see a catch block swallowing exceptions, so I don't see how he'd miss any exceptions flying out of there, and that's the only way that Close() isn't getting called anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.