<PackageReference Include="System.Reactive" Version="6.0.1-preview.1" />

AsyncLock

public sealed class AsyncLock : IDisposable
Asynchronous lock.
using System.Collections.Generic; using System.Runtime.CompilerServices; namespace System.Reactive.Concurrency { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public sealed class AsyncLock : IDisposable { private bool _isAcquired; private bool _hasFaulted; private readonly object _guard = new object(); [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0, 1, 1, 2, 1, 2 })] private Queue<(Action<Delegate, object> action, Delegate delegate, object state)> _queue; public void Wait(Action action) { if (action == null) throw new ArgumentNullException("action"); Wait(action, delegate(Action closureAction) { closureAction(); }); } internal void Wait<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, Action<TState> action) { if (action == null) throw new ArgumentNullException("action"); Wait(state, action, delegate(Delegate actionObject, object stateObject) { ((Action<TState>)actionObject)((TState)stateObject); }); } private void Wait([System.Runtime.CompilerServices.Nullable(2)] object state, Delegate delegate, [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 1, 2 })] Action<Delegate, object> action) { lock (_guard) { if (_hasFaulted) return; if (_isAcquired) { Queue<(Action<Delegate, object>, Delegate, object)> queue = _queue; if (queue == null) queue = (_queue = new Queue<(Action<Delegate, object>, Delegate, object)>()); queue.Enqueue((action, delegate, state)); return; } _isAcquired = true; } while (true) { try { action(delegate, state); } catch { lock (_guard) { _queue = null; _hasFaulted = true; } throw; } lock (_guard) { Queue<(Action<Delegate, object>, Delegate, object)> queue2 = _queue; if (queue2 == null || queue2.Count == 0) { _isAcquired = false; return; } (Action<Delegate, object>, Delegate, object) valueTuple = queue2.Dequeue(); action = valueTuple.Item1; delegate = valueTuple.Item2; state = valueTuple.Item3; } } } public void Dispose() { lock (_guard) { _queue = null; _hasFaulted = true; } } } }