当受到Mutex保护的访问时,共享XML上的“根元素缺失”

时间:2015-10-31 02:01:41

标签: c# synchronization mutex xmlreader

我在两个进程,本地系统服务和WinForms应用程序之间共享了一个settings.xml文档。对文档的访问由互斥锁控制。两个应用程序都在启动时读取并更新xml文件。

在测试期间,如果我重新启动测试计算机以使服务自动启动并且User App从Startup文件夹启动,服务会在大约10%到20%的测试中引发以下异常运行:

Exception Data:
Exception Type: System.InvalidOperationException
Message: There is an error in XML document (0, 0).
Source: System.Xml
Method: System.Object Deserialize(System.Xml.XmlReader, System.String, System.Xml.Serialization.XmlDeserializationEvents)
Stack Trace: 
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
   at lib.ServiceSettings.ReadFromFile() in ServiceSettings.cs:line 107
   at svc.SystemService.settingsFile_Changed(Object sender, FileSystemEventArgs e) in Settings.cs:line 152
------------------
InnerException Data:
Exception Type: System.Xml.XmlException
Message: Root element is missing.
Source: System.Xml
Method: Void Throw(System.Exception)
Stack Trace: 
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XmlReader.MoveToContent()
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderServiceSettings.Read4_ServiceSettings()

这是竞争条件,但我无法在调试时复制它。两个应用程序都使用static类中的ServiceSettings方法来读取设置文件:

public static ServiceSettings ReadFromFile()
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(ServiceSettings), ServiceConstants.defaultXmlNamespace);

    using (FileStream fileStream = new FileStream(ServiceConstants.defaultFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        using (XmlReader xmlReader = XmlReader.Create(fileStream))
        {
            return (ServiceSettings)xmlSerializer.Deserialize(xmlReader); // line 107 exception thrown
        }
    }
}

调用堆栈指向FileSystemWatcher.Changed事件,其中再次读入设置文件 - 在这种情况下用户应用程序更新文件后

private void settingsFile_Changed(object sender, FileSystemEventArgs e)
{
    settingsMutex.WaitOne();

    try
    {
        settings = ServiceSettings.ReadFromFile(); // line 152 exception thrown
    }
    catch (InvalidOperationException ex)
    {
        LogExceptionData(ex);
        throw;
    }

    settingsMutex.ReleaseMutex();
}

当我查看xml文档时,格式似乎符合预期:

<?xml version="1.0" encoding="UTF-8"?>
<ServiceSettings xmlns="svc.settings">
...
</ServiceSettings>

我看不出这里会出现什么问题。我怀疑它可能与我对FileStream对象的使用有关,但我无法绕过这一个。有没有人对我有任何线索?提前谢谢!

修改

为两个应用程序创建互斥锁的方式相同:

private static Mutex settingsMutex = null;

private void InitialiseSettings()
{   
    settingsMutex = new Mutex(false, ServiceConstants.mutexName);
    ...

共享库中定义了ServiceConstants类,其中包含互斥锁名称的静态字符串:

public class ServiceConstants
{
    public const string mutexName = "svc.settings.mutex";
    ...

创建机器范围的互斥锁是否正确?

0 个答案:

没有答案