Как лучше всего синхронизировать доступ XmlWriter к файлу, чтобы предотвратить IOExceptions?
-
22-07-2019 - |
Вопрос
В приложении есть несколько мест, которые вызывают 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;
}
}
ОБНОВЛЯТЬ:Похоже, проблема не только в вызовах этой функции, но и в том, что другой поток читает файл, пока эта функция записывает его.Каков наилучший способ блокировки, чтобы мы не пытались записывать в файл во время его чтения?
Решение
Использование блокировки может решить вашу проблему с параллелизмом и, таким образом, избежать исключения IOException, но вы должны помнить об использовании одного и того же объекта в SaveToDisk и ReadFromDisk (я предполагаю, что это функция чтения), в противном случае блокировку полностью бесполезно, только когда вы читать.
private static readonly object syncLock = new object();
public void SaveToDisk()
{
lock(syncLock)
{
... write code ...
}
}
public void ReadFromDisk()
{
lock(syncLock)
{
... read code ...
}
}
Другие советы
Статическая блокировка должна выполнять свою работу быстро и просто:
private static readonly object syncLock = new object();
затем...
public void SaveToDisk()
{
lock(syncLock)
{
...your code...
}
}
Вы также можете использовать [MethodImpl(MethodImplOptions.Synchronized)]
(на статический метод, который принимает экземпляр в качестве аргумента — например, метод расширения), но явная блокировка более универсальна.
Я бы на самом деле использовал 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 чтобы последующее чтение не завершилось неудачей.