Heim >Backend-Entwicklung >C++ >Wie vermeide ich zeitweilige Dateizugriffsfehler mit asynchroner Sperrung in C#?

Wie vermeide ich zeitweilige Dateizugriffsfehler mit asynchroner Sperrung in C#?

Patricia Arquette
Patricia ArquetteOriginal
2025-01-15 06:03:44815Durchsuche

How to Avoid Intermittent File Access Errors with Asynchronous Locking 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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn