2009-05-11 6 views
1

Ich habe this Open-Source-Bibliothek, die ich habe einige Probleme bei der Behebung eines Problems ... Diese Bibliothek ermöglicht auf einfache Weise eine XML-Datei zum Speichern von Anwendungseinstellungen erstellen. Aber ich habe ein Problem beim Speichern der Änderungen.Speichern XML-Stream in C# sagt, dass es von einem anderen Prozess verwendet wird

Ich habe eine andere Anwendung, wo ich diese Bibliothek verwende und jedes Mal, wenn das Anwendungsfenster die Größenänderung vorgenommen wird, rufe ich die Save() -Methode der Bibliothek auf, um die Fenstergröße/-position in der XML-Datei zu speichern.

Die meiste Zeit funktioniert es gut, alles ist gespeichert. Hin und wieder bekomme ich eine Ausnahme, dass die Datei von einem anderen Prozess verwendet wird.

Ich muss wirklich sicherstellen, dass Änderungen jedes Mal gespeichert werden, wenn die Save() -Methode aufgerufen wird, ich muss diese Ausnahme irgendwie behandeln oder verhindern, dass es passiert.

Was sind Ihre Vorschläge für den besten Umgang mit dieser Situation?

Der Code für die Save() Methode ist folgende:

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(); 
} 
+0

Ich sehe, dass Sie die Antwort angenommen haben, die Lock-Anweisung zu setzen, und das ist cool, aber ich würde Sie davor warnen, die using-Anweisung in Ihrem Code zu verwenden. Es wird sichergestellt, dass Sie Ihre Ressourcen immer wie erwartet bereinigen. Wenn Sie eine Ausnahme haben, schließen Sie die Datei nicht korrekt und haben möglicherweise weiterhin Konflikte in der Datei, da die Sperre nicht hilft. –

+0

Ich benutze es auch, danke für die Pflege. Ich habe diese Antwort akzeptiert, weil sie das Problem in dieser Frage behoben hat.Ich habe nicht mehr die Ausnahme, die ich hatte und hatte nie eine andere (nicht sagen, ich werde es in Zukunft nicht haben), also ist das Problem behoben. Trotzdem, deine zusätzlichen Infos sind gut und deshalb habe ich für "hilfreiche Antworten" gestimmt :) –

Antwort

1

Es könnte der Fall sein, dass die Fenster-Resize-abgeschlossen-Ereignisse so schnell feuern, dass die Speicherfunktion aufgerufen wird, die erneut aufgerufen wird, bevor es das erste Mal ausgeführt wird. Dies würde zu dem Fehler führen, den Sie beschreiben (der andere Prozess, der die Datei verwendet, ist ... SIE!). Try surrounding your code with a lock, thusly:

lock(some_shared_object) 
{ 
    //Your code here 
} 
3

XmlWriter ist IDisposable. Sie sollten es in eine using() -Klausel einfügen. http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx

+0

Kannst du erklären warum ich deine fast sicher mit() anstelle von lock() benutzen sollte? Bis jetzt verstehe ich die Gründe für das Schloss und ich denke, es macht Sinn, nicht für die Verwendung obwohl ... –

+0

Whoops; Ich habe vielleicht falsch verstanden. Die using() -Klausel ist zwingend für eine Klasse, die IDisposable implementiert. Die Sperre kann auch erforderlich sein, abhängig davon, ob Ihre Größenänderungslogik verschachtelte oder gleichzeitige Größenänderungsereignisse zulässt. – Cheeso

1

Auch Sie könnten versuchen, eine Lock-Anweisung zu verwenden. Es könnte sein, dass sich die Methoden gegenseitig überholen.

+0

Können Sie bitte genauer? Nicht sicher, was eine "lock-Anweisung" ist ... –

+0

Es ist 99.44% sicher, dass es die using() -Anweisung ist. Sie brauchen kein Schloss. – Cheeso

+0

Ich bin nicht sicher, dass die using() das Grundproblem ist, da er einen Aufruf an XmlWriter.Close() hat. Ich sehe keinen Catch-Block, der Ausnahmen verschluckt, also sehe ich nicht, wie er irgendwelche Ausnahmen verpassen würde, und das ist der einzige Weg, wie Close() sowieso nicht aufgerufen wird. – GWLlosa

2

Ich habe mit einer Kombination der Antworten gehen schon hier gegeben.

Ihr XmlWriter sollte aus verschiedenen Gründen in einem Verwendungsblock sein. Sie sollten es so entsorgen, dass Ihre Ressourcen so schnell wie möglich freigegeben werden. Was passiert auch, wenn Sie beim Interagieren eine Ausnahme auslösen? Die Datei wird nicht ordnungsgemäß geschlossen, bis der Finalizer startet und Ihre Ressourcen freigibt.

Auch mit der Anweisung using, haben Sie möglicherweise Konflikte in der Datei und müssen den Code speichern in eine lock-Anweisung. Die Methode ist von Natur aus nicht reentrant, da die Datei eine gemeinsam genutzte Ressource ist. Wenn Sie mehrere Threads verwenden, kann es sein, dass die Sperre aufgehoben wird. Sie können jedoch sicherstellen, dass Sie den Zugriff auf die Datei ordnungsgemäß steuern.

Die andere Sache, die Sie beachten sollten, ist, dass Sie den Speichervorgang möglicherweise in einen Hintergrundthread verschieben möchten, um die Datei zu schreiben. Wenn Sie eine große Einstellungsdatei erhalten, können Sie seltsame UI-Interaktionen verursachen, da Sie auf die Datei warten müssen, um jedes Mal zu schreiben, wenn der Benutzer die Größe ändert und dies im UI-Thread geschieht. Wenn Sie dies tun, müssen Sie den Zugriff auf die Dateiressource definitiv sperren.

Verwandte Themen