Qual è il modo migliore per sincronizzare l'accesso XmlWriter a un file per prevenire IOExceptions?

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

Domanda

Vi sono più posizioni in un'applicazione che chiamano XmlWriter.Create sullo stesso file, tutte accessibili tramite la seguente funzione. Quando uno chiama mentre un altro sta ancora scrivendo, ricevo una IOException. Qual è il modo migliore per bloccare o sincronizzare l'accesso?

Ecco la funzione che viene utilizzata:

        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;
        }
    }

AGGIORNAMENTO: Sembra che il problema non sia solo dalle chiamate a questa funzione, ma perché un altro thread sta leggendo il file mentre questa funzione sta scrivendo. Qual è il modo migliore per bloccare, quindi non proviamo a scrivere nel file mentre viene letto?

È stato utile?

Soluzione

L'uso di un blocco può risolvere il problema di concorrenza ed evitare quindi l'IOException, ma è necessario ricordare di utilizzare lo stesso oggetto su SaveToDisk e ReadFromDisk (suppongo che questa sia la funzione di lettura), altrimenti è totalmente inutile bloccare solo quando si lettura.

private static readonly object syncLock = new object();

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

public void ReadFromDisk()
{
     lock(syncLock)
     {
          ... read code ...
     }
}

Altri suggerimenti

Un blocco statico dovrebbe fare il lavoro in modo rapido e semplice:

private static readonly object syncLock = new object();

poi ...

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

Puoi anche usare [MethodImpl (MethodImplOptions.Synchronized)] (su un metodo statico che accetta l'istanza come argomento, ad esempio un metodo di estensione), ma un blocco esplicito è più versatile.

Utilizzerei effettivamente un ReaderWriterLock per massimizzare la concorrenza. Puoi consentire a più lettori ma solo un autore per volta.

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();
     }
}

Assicurati solo di aprire il file con FileShare.Read in modo che le letture successive non falliscano.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top