Qual é a melhor maneira de sincronizar o acesso XmlWriter para um arquivo para evitar IOExceptions?

StackOverflow https://stackoverflow.com/questions/442235

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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top