QueueSemaphore.cs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace EVCB_OCPP.WSServer.Helper;
  9. public class QueueSemaphore
  10. {
  11. public QueueSemaphore(int maxLimit)
  12. {
  13. this._queue = new();
  14. this._semaphore = new(maxLimit);
  15. }
  16. private readonly ConcurrentQueue<SemaphoreSlim> _queue;
  17. private readonly SemaphoreSlim _semaphore;
  18. public async Task<QueueSemaphoreToken> GetToken()
  19. {
  20. //if (_semaphore.Wait(0))
  21. //{
  22. // return CreateToken();
  23. //}
  24. SemaphoreSlim _selfSemaphore = new(0);
  25. _queue.Enqueue(_selfSemaphore);
  26. TryDequeue();
  27. await _selfSemaphore.WaitAsync();
  28. return CreateToken();
  29. }
  30. private QueueSemaphoreToken CreateToken()
  31. {
  32. QueueSemaphoreToken token = new ();
  33. token.OnDisposed += Token_OnDisposed;
  34. return token;
  35. }
  36. private void Token_OnDisposed(object sender, EventArgs e)
  37. {
  38. var token = sender as QueueSemaphoreToken;
  39. token.OnDisposed -= Token_OnDisposed;
  40. _semaphore.Release();
  41. TryDequeue();
  42. }
  43. private bool TryDequeue()
  44. {
  45. if (!_semaphore.Wait(0))
  46. {
  47. return false;
  48. }
  49. if (_queue.TryDequeue(out var semaphore))
  50. {
  51. semaphore.Release();
  52. return true;
  53. }
  54. _semaphore.Release();
  55. return false;
  56. }
  57. }
  58. public class QueueSemaphoreToken : IDisposable
  59. {
  60. internal event EventHandler OnDisposed;
  61. public void Dispose()
  62. {
  63. OnDisposed?.Invoke(this, EventArgs.Empty);
  64. }
  65. }