Maison >développement back-end >C++ >Comment éviter les erreurs d'accès intermittent aux fichiers avec le verrouillage asynchrone en 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>
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>
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!