QueueSemaphore.cs 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. return false;
  55. }
  56. }
  57. public class QueueSemaphoreToken : IDisposable
  58. {
  59. internal event EventHandler OnDisposed;
  60. public void Dispose()
  61. {
  62. OnDisposed?.Invoke(this, EventArgs.Empty);
  63. }
  64. }