using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace EVCB_OCPP.WSServer.Helper; public class QueueSemaphore { public QueueSemaphore(int maxLimit) { this._queue = new(); this._semaphore = new(maxLimit); } private readonly ConcurrentQueue _queue; private readonly SemaphoreSlim _semaphore; public async Task GetToken() { //if (_semaphore.Wait(0)) //{ // return CreateToken(); //} SemaphoreSlim _selfSemaphore = new(0); _queue.Enqueue(_selfSemaphore); TryDequeue(); await _selfSemaphore.WaitAsync(); return CreateToken(); } private QueueSemaphoreToken CreateToken() { QueueSemaphoreToken token = new (); token.OnDisposed += Token_OnDisposed; return token; } private void Token_OnDisposed(object sender, EventArgs e) { var token = sender as QueueSemaphoreToken; token.OnDisposed -= Token_OnDisposed; _semaphore.Release(); TryDequeue(); } private bool TryDequeue() { if (!_semaphore.Wait(0)) { return false; } if (_queue.TryDequeue(out var semaphore)) { semaphore.Release(); return true; } _semaphore.Release(); return false; } } public class QueueSemaphoreToken : IDisposable { internal event EventHandler OnDisposed; public void Dispose() { OnDisposed?.Invoke(this, EventArgs.Empty); } }