Maison > développement back-end > C++ > Comment éviter les erreurs d'accès intermittent aux fichiers avec le verrouillage asynchrone en C# ?

Comment éviter les erreurs d'accès intermittent aux fichiers avec le verrouillage asynchrone en C# ?

Patricia Arquette
Libérer: 2025-01-15 06:03:44
original
814 Les gens l'ont consulté

How to Avoid Intermittent File Access Errors with Asynchronous Locking in C#?

Résolution des erreurs d'accès intermittent aux fichiers avec le verrouillage asynchrone en C#

Le verrouillage asynchrone, en particulier lors de l'utilisation d'une URL hachée et d'une classe comme AsyncDuplicateLock, peut parfois entraîner des erreurs intermittentes d'accès aux fichiers. Cela provient souvent d'une mauvaise gestion des sémaphores dans un dictionnaire concurrent. Une première approche erronée pourrait ressembler à ceci :

<code class="language-csharp">SemaphoreSlim locker;
if (SemaphoreSlims.TryRemove(s, out locker))
{
    locker.Release();
    locker.Dispose();
}</code>
Copier après la connexion

Le problème ici est de supprimer le sémaphore avant de le libérer. Cela crée un roulement excessif des sémaphores, conduisant à une utilisation continue du sémaphore même après sa suppression du dictionnaire.

Une solution robuste utilise le comptage de références pour gérer la durée de vie des sémaphores :

<code class="language-csharp">public sealed class AsyncDuplicateLock
{
    private sealed class RefCounted<T>
    {
        public RefCounted(T value)
        {
            RefCount = 1;
            Value = value;
        }

        public int RefCount { get; set; }
        public T Value { get; private set; }
    }

    private static readonly Dictionary<object, RefCounted<SemaphoreSlim>> SemaphoreSlims
                        = new Dictionary<object, RefCounted<SemaphoreSlim>>();

    private SemaphoreSlim GetOrCreate(object key)
    {
        RefCounted<SemaphoreSlim> item;
        lock (SemaphoreSlims)
        {
            if (SemaphoreSlims.TryGetValue(key, out item))
            {
                ++item.RefCount;
            }
            else
            {
                item = new RefCounted<SemaphoreSlim>(new SemaphoreSlim(1, 1));
                SemaphoreSlims[key] = item;
            }
        }
        return item.Value;
    }

    public IDisposable Lock(object key)
    {
        GetOrCreate(key).Wait();
        return new Releaser { Key = key };
    }

    public async Task<IDisposable> LockAsync(object key)
    {
        await GetOrCreate(key).WaitAsync().ConfigureAwait(false);
        return new Releaser { Key = key };
    }

    private sealed class Releaser : IDisposable
    {
        public object Key { get; set; }

        public void Dispose()
        {
            RefCounted<SemaphoreSlim> item;
            lock (SemaphoreSlims)
            {
                item = SemaphoreSlims[Key];
                --item.RefCount;
                if (item.RefCount == 0)
                    SemaphoreSlims.Remove(Key);
            }
            item.Value.Release();
        }
    }
}</code>
Copier après la connexion

Ce code révisé utilise un RefCounted<T> wrapper pour suivre les références de sémaphore. Un sémaphore n'est supprimé du dictionnaire que lorsque son nombre de références atteint zéro, garantissant une libération correcte et empêchant une suppression prématurée, éliminant ainsi les erreurs intermittentes d'accès aux fichiers.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal