C# の非同期ロックを使用した断続的なファイル アクセス エラーの解決
非同期ロック、特にハッシュされた URL や AsyncDuplicateLock
のようなクラスを使用する場合、断続的なファイル アクセス エラーが発生することがあります。 これは多くの場合、同時ディクショナリ内でのセマフォの不適切な処理が原因で発生します。 初期の欠陥のあるアプローチは次のようになります:
<code class="language-csharp">SemaphoreSlim locker; if (SemaphoreSlims.TryRemove(s, out locker)) { locker.Release(); locker.Dispose(); }</code>
ここでの問題は、セマフォを解放する前に削除することです。これにより、セマフォの過剰なチャーンが発生し、辞書から削除された後もセマフォが使用され続けることになります。
堅牢なソリューションでは、参照カウントを使用してセマフォの有効期間を管理します。
<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>
この改訂されたコードは、RefCounted<T>
ラッパーを使用してセマフォ参照を追跡します。 セマフォは参照カウントが 0 に達した場合にのみディクショナリから削除されるため、適切な解放が確保され、早期の破棄が防止され、断続的なファイル アクセス エラーが排除されます。
以上がC# の非同期ロックで断続的なファイル アクセス エラーを回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。