diff --git a/src/Main/Core/Project/ICSharpCode.Core.csproj b/src/Main/Core/Project/ICSharpCode.Core.csproj
index 3e96226f01..fbffc31f55 100644
--- a/src/Main/Core/Project/ICSharpCode.Core.csproj
+++ b/src/Main/Core/Project/ICSharpCode.Core.csproj
@@ -99,6 +99,7 @@
+
diff --git a/src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs b/src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs
index cc8256f370..2aa3555754 100644
--- a/src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs
+++ b/src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs
@@ -8,6 +8,7 @@
using System;
using System.IO;
using System.Text;
+using System.Threading;
using System.Xml;
namespace ICSharpCode.Core
@@ -90,12 +91,14 @@ namespace ICSharpCode.Core
return false;
}
try {
- using (XmlTextReader reader = new XmlTextReader(fileName)) {
- while (reader.Read()){
- if (reader.IsStartElement()) {
- if (reader.LocalName == propertyXmlRootNodeName) {
- properties.ReadProperties(reader, propertyXmlRootNodeName);
- return true;
+ using (LockPropertyFile()) {
+ using (XmlTextReader reader = new XmlTextReader(fileName)) {
+ while (reader.Read()){
+ if (reader.IsStartElement()) {
+ if (reader.LocalName == propertyXmlRootNodeName) {
+ properties.ReadProperties(reader, propertyXmlRootNodeName);
+ return true;
+ }
}
}
}
@@ -108,15 +111,38 @@ namespace ICSharpCode.Core
public static void Save()
{
- string fileName = Path.Combine(configDirectory, propertyFileName);
- using (XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8)) {
+ using (MemoryStream ms = new MemoryStream()) {
+ XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
writer.Formatting = Formatting.Indented;
writer.WriteStartElement(propertyXmlRootNodeName);
properties.WriteProperties(writer);
writer.WriteEndElement();
+ writer.Flush();
+
+ ms.Position = 0;
+ string fileName = Path.Combine(configDirectory, propertyFileName);
+ using (LockPropertyFile()) {
+ using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) {
+ ms.WriteTo(fs);
+ }
+ }
}
}
+ ///
+ /// Acquires an exclusive lock on the properties file so that it can be opened safely.
+ ///
+ public static IDisposable LockPropertyFile()
+ {
+ Mutex mutex = new Mutex(false, "PropertyServiceSave-30F32619-F92D-4BC0-BF49-AA18BF4AC313");
+ mutex.WaitOne();
+ return new CallbackOnDispose(
+ delegate {
+ mutex.ReleaseMutex();
+ mutex.Close();
+ });
+ }
+
static void PropertiesPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null) {
diff --git a/src/Main/Core/Project/Src/Util/CallbackOnDispose.cs b/src/Main/Core/Project/Src/Util/CallbackOnDispose.cs
new file mode 100644
index 0000000000..1db64aa893
--- /dev/null
+++ b/src/Main/Core/Project/Src/Util/CallbackOnDispose.cs
@@ -0,0 +1,35 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Threading;
+
+namespace ICSharpCode.Core
+{
+ ///
+ /// Invokes a callback when this class is dispsed.
+ ///
+ sealed class CallbackOnDispose : IDisposable
+ {
+ // TODO: in 4.0, use System.Action and make this class public
+ System.Threading.ThreadStart callback;
+
+ public CallbackOnDispose(System.Threading.ThreadStart callback)
+ {
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+ this.callback = callback;
+ }
+
+ public void Dispose()
+ {
+ System.Threading.ThreadStart action = Interlocked.Exchange(ref callback, null);
+ if (action != null)
+ action();
+ }
+ }
+}