Quel est le meilleur moyen de synchroniser l'accès XmlWriter à un fichier pour empêcher les exceptions IO?

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

Question

Il existe plusieurs emplacements dans une application qui appellent XmlWriter.Create sur le même fichier, tous accessibles via la fonction suivante. Lorsqu'un appelant pendant qu'un autre écrit encore, j'obtiens une exception IOException. Quel est le meilleur moyen de verrouiller ou de synchroniser les accès?

Voici la fonction utilisée:

        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: Il semble que le problème ne provienne pas uniquement d'appels à cette fonction, mais du fait qu'un autre thread est en train de lire le fichier alors que cette fonction écrit. Quel est le meilleur moyen de verrouiller pour ne pas essayer d’écrire dans le fichier en cours de lecture?

Était-ce utile?

La solution

L'utilisation d'un verrou peut résoudre votre problème de simultanéité et éviter ainsi l'exception IOException, mais vous devez vous rappeler d'utiliser le même objet sur SaveToDisk et ReadFromDisk (je suppose que c'est la fonction de lecture), sinon il est totalement inutile de verrouiller uniquement lire.

private static readonly object syncLock = new object();

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

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

Autres conseils

Un verrou statique devrait faire le travail rapidement et simplement:

private static readonly object syncLock = new object();

alors ...

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

Vous pouvez également utiliser [MethodImpl (MethodImplOptions.Synchronized)] (sur une méthode static qui accepte l'instance en tant qu'argument - par exemple, une méthode d'extension), mais un verrou explicite est plus polyvalent.

Je voudrais en fait utiliser un ReaderWriterLock pour maximiser la concurrence. Vous pouvez autoriser plusieurs lecteurs, mais un seul auteur à la fois.

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

Assurez-vous simplement d’ouvrir le fichier avec FileShare.Read pour que les lectures suivantes n'échouent pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top