Каков наилучший способ синхронизации доступа XmlWriter к файлу для предотвращения исключений IOException? - PullRequest
4 голосов
/ 14 января 2009

В приложении есть несколько мест, в которых вызывается XmlWriter.Create для одного и того же файла, доступ к которым осуществляется через следующую функцию. Когда один звонит, а другой все еще пишет, я получаю IOException. Какой лучший способ заблокировать или синхронизировать доступ?

Вот функция, которая используется:

        public void SaveToDisk()
    {
        try
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            using (XmlWriter writer = XmlWriter.Create(SaveFileAbsolutePath, settings))
            {
                XamlWriter.Save(this, writer);
                writer.Close();
            }

        }
        catch (Exception ex)
        {
            // Log the error
            System.Diagnostics.Debug.WriteLine(ex.Message);

            // Rethrow so we know about the error
            throw;
        }
    }

ОБНОВЛЕНИЕ: Похоже, проблема не только в вызовах этой функции, а в том, что другой поток читает файл, пока эта функция выполняет запись. Какой лучший способ блокировки, чтобы мы не пытались записать файл во время его чтения?

Ответы [ 3 ]

4 голосов
/ 14 января 2009

Использование блокировки может решить вашу проблему параллелизма и, таким образом, избежать исключения IOException, но вы должны помнить, чтобы использовать один и тот же объект либо в SaveToDisk, либо в ReadFromDisk (я предполагаю, что это функция чтения), в противном случае блокировку полностью бесполезно, только когда вы читать.

private static readonly object syncLock = new object();

public void SaveToDisk()
{
     lock(syncLock)
     {
          ... write code ...
     }
}

public void ReadFromDisk()
{
     lock(syncLock)
     {
          ... read code ...
     }
}
3 голосов
/ 14 января 2009

Статический замок должен выполнять работу быстро и просто:

private static readonly object syncLock = new object();

тогда ...

public void SaveToDisk()
{
    lock(syncLock)
    {
        ...your code...
    }
}

Вы также можете использовать [MethodImpl(MethodImplOptions.Synchronized)] (для статического метода, который принимает экземпляр в качестве аргумента - например, метод расширения), но явная блокировка более универсальна.

1 голос
/ 14 февраля 2011

Я бы на самом деле использовал ReaderWriterLock , чтобы максимизировать параллелизм. Вы можете разрешить несколько читателей, но только один писатель одновременно.

private ReaderWriterLock myLock = new ReaderWriterLock();

public void SaveToDisk()
{
     myLock.AcquireWriterLock();
     try
     {
          ... write code ...
     } 
     finally
     {
          myLock.ReleaseWriterLock();
     }
}

public void ReadFromDisk()
{
     myLock.AcquireReaderLock();
     try
     {
          ... read code ...
     } 
     finally
     {
          myLock.ReleaseReaderLock();
     }
}

Просто откройте файл с помощью FileShare.Read , чтобы последующие операции чтения не завершились.

...