Heim >Backend-Entwicklung >C++ >Wie vermeide ich zeitweilige Dateizugriffsfehler mit asynchroner Sperrung in C#?
Zeitweilige Dateizugriffsfehler mit asynchroner Sperrung in C# lösen
Asynchrones Sperren, insbesondere bei Verwendung einer gehashten URL und einer Klasse wie AsyncDuplicateLock
, kann manchmal zu zeitweiligen Dateizugriffsfehlern führen. Dies ist häufig auf eine unsachgemäße Semaphorbehandlung innerhalb eines gleichzeitigen Wörterbuchs zurückzuführen. Ein erster fehlerhafter Ansatz könnte so aussehen:
<code class="language-csharp">SemaphoreSlim locker; if (SemaphoreSlims.TryRemove(s, out locker)) { locker.Release(); locker.Dispose(); }</code>
Das Problem hierbei besteht darin, das Semaphor zu entfernen, bevor es freigegeben wird. Dies führt zu einer übermäßigen Semaphor-Abwanderung, was dazu führt, dass das Semaphor auch nach seiner Entfernung aus dem Wörterbuch weiterhin verwendet wird.
Eine robuste Lösung nutzt Referenzzählung, um die Lebensdauer von Semaphoren zu verwalten:
<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>
Dieser überarbeitete Code verwendet einen RefCounted<T>
-Wrapper, um Semaphorreferenzen zu verfolgen. Ein Semaphor wird nur dann aus dem Wörterbuch entfernt, wenn sein Referenzzähler Null erreicht, wodurch eine ordnungsgemäße Freigabe sichergestellt und eine vorzeitige Löschung verhindert wird, wodurch die zeitweiligen Dateizugriffsfehler vermieden werden.
Das obige ist der detaillierte Inhalt vonWie vermeide ich zeitweilige Dateizugriffsfehler mit asynchroner Sperrung in C#?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!