Корневой элемент отсутствует в общем XML, когда доступ защищен Mutex

У меня есть документ settings.xml, совместно используемый двумя процессами, службой локальной системы и приложением WinForms. Доступ к документу контролируется мьютексом. Оба приложения читают и обновляют файл xml при запуске.

Если во время тестирования я перезапущу тестовый компьютер, чтобы служба автоматически запускалась, а пользовательское приложение запускалось из папки автозагрузки, служба выдает следующее исключение примерно в 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";
    ...

Правильно ли это для создания мьютекса на уровне машины?


person khargoosh    schedule 31.10.2015    source источник
comment
99% вы создаете мьютекс неправильно. Пожалуйста, рассмотрите возможность обновить свой пост с кодом, показывающим создание мьютекса на уровне машины.   -  person Alexei Levenkov    schedule 31.10.2015
comment
Это имело бы смысл... Я добавил код выше.   -  person khargoosh    schedule 31.10.2015
comment
Спасибо за эту ссылку Алексей, за все поиски не наткнулся. Имейте в виду, что до вашего комментария о мьютексе я не понимал, что это проблема.   -  person khargoosh    schedule 31.10.2015
comment
Ага! Причина, по которой я не мог воспроизвести во время отладки, заключается в том, что сеанс отладки службы был в VS (как консольное приложение) и запускался под моим сеансом пользователя, где мьютекс был виден обоим приложениям.   -  person khargoosh    schedule 31.10.2015
comment
Подтвердите, что добавление префикса "Global\" к имени вашего мьютекса решило вашу проблему. Если да, то этот вопрос следует закрыть как дубликат вопроса, предложенного комментатором @AlexeiLevenkov.   -  person Peter Duniho    schedule 31.10.2015
comment
Похоже, проблема решена. Я думаю, что его можно закрыть.   -  person khargoosh    schedule 31.10.2015