Qual é a melhor maneira de sincronizar o acesso XmlWriter para um arquivo para evitar IOExceptions?
-
22-07-2019 - |
Pergunta
Há vários lugares em uma aplicação que chamada XmlWriter.Create no mesmo arquivo, todos acessados ??através do seguinte função. Quando um chamadas enquanto outro ainda está escrevendo, eu recebo um IOException. Qual é a melhor maneira de bloquear ou sincronizar o acesso?
Aqui está a função que está sendo usado:
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;
}
}
UPDATE: Parece que o problema não é apenas de chamadas para esta função, mas porque outro segmento está lendo o arquivo enquanto esta função está escrevendo para é. Qual é a melhor maneira de bloqueio de modo que não tentar escrever para o arquivo enquanto ele está sendo lido?
Solução
Usando um bloqueio pode resolver o seu problema de concorrência e, assim, evitar o IOException, mas você deve se lembrar de usar o mesmo objeto seja em SaveToDisk e ReadFromDisk (i assumir essa é a função de leitura), caso contrário é totalmente inútil para bloquear somente quando você ler.
private static readonly object syncLock = new object();
public void SaveToDisk()
{
lock(syncLock)
{
... write code ...
}
}
public void ReadFromDisk()
{
lock(syncLock)
{
... read code ...
}
}
Outras dicas
Um bloqueio estática deve fazer o trabalho de forma rápida e simples:
private static readonly object syncLock = new object();
então ...
public void SaveToDisk()
{
lock(syncLock)
{
...your code...
}
}
Você também pode usar [MethodImpl(MethodImplOptions.Synchronized)]
(em um estática método que aceita a instância como um argumento - por exemplo, um método de extensão)., Mas um bloqueio explícito é mais versátil
Eu realmente usar um ReaderWriterLock para simultaneidade maximizar. Você pode permitir que vários leitores, mas apenas um escritor de cada vez.
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();
}
}
Apenas certifique-se de abrir o arquivo com FileShare.Read para que as leituras subsequentes não falham.