LifetimeHttpHandlerCleaner.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Diagnostics;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. namespace FastGithub.Http
  7. {
  8. /// <summary>
  9. /// 表示LifetimeHttpHandler清理器
  10. /// </summary>
  11. sealed class LifetimeHttpHandlerCleaner
  12. {
  13. /// <summary>
  14. /// 当前监视生命周期的记录的数量
  15. /// </summary>
  16. private int trackingEntryCount = 0;
  17. /// <summary>
  18. /// 监视生命周期的记录队列
  19. /// </summary>
  20. private readonly ConcurrentQueue<TrackingEntry> trackingEntries = new();
  21. /// <summary>
  22. /// 获取或设置清理的时间间隔
  23. /// 默认10s
  24. /// </summary>
  25. public TimeSpan CleanupInterval { get; set; } = TimeSpan.FromSeconds(10d);
  26. /// <summary>
  27. /// 添加要清除的httpHandler
  28. /// </summary>
  29. /// <param name="handler">httpHandler</param>
  30. public void Add(LifetimeHttpHandler handler)
  31. {
  32. var entry = new TrackingEntry(handler);
  33. this.trackingEntries.Enqueue(entry);
  34. // 从0变为1,要启动清理作业
  35. if (Interlocked.Increment(ref this.trackingEntryCount) == 1)
  36. {
  37. this.StartCleanup();
  38. }
  39. }
  40. /// <summary>
  41. /// 启动清理作业
  42. /// </summary>
  43. private async void StartCleanup()
  44. {
  45. await Task.Yield();
  46. while (this.Cleanup() == false)
  47. {
  48. await Task.Delay(this.CleanupInterval);
  49. }
  50. }
  51. /// <summary>
  52. /// 清理失效的拦截器
  53. /// 返回是否完全清理
  54. /// </summary>
  55. /// <returns></returns>
  56. private bool Cleanup()
  57. {
  58. var cleanCount = this.trackingEntries.Count;
  59. for (var i = 0; i < cleanCount; i++)
  60. {
  61. this.trackingEntries.TryDequeue(out var entry);
  62. Debug.Assert(entry != null);
  63. if (entry.CanDispose == false)
  64. {
  65. this.trackingEntries.Enqueue(entry);
  66. continue;
  67. }
  68. entry.Dispose();
  69. if (Interlocked.Decrement(ref this.trackingEntryCount) == 0)
  70. {
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. /// <summary>
  77. /// 表示监视生命周期的记录
  78. /// </summary>
  79. private class TrackingEntry : IDisposable
  80. {
  81. /// <summary>
  82. /// 用于释放资源的对象
  83. /// </summary>
  84. private readonly IDisposable disposable;
  85. /// <summary>
  86. /// 监视对象的弱引用
  87. /// </summary>
  88. private readonly WeakReference weakReference;
  89. /// <summary>
  90. /// 获取是否可以释放资源
  91. /// </summary>
  92. /// <returns></returns>
  93. public bool CanDispose => this.weakReference.IsAlive == false;
  94. /// <summary>
  95. /// 监视生命周期的记录
  96. /// </summary>
  97. /// <param name="handler">激活状态的httpHandler</param>
  98. public TrackingEntry(LifetimeHttpHandler handler)
  99. {
  100. this.disposable = handler.InnerHandler!;
  101. this.weakReference = new WeakReference(handler);
  102. }
  103. /// <summary>
  104. /// 释放资源
  105. /// </summary>
  106. public void Dispose()
  107. {
  108. try
  109. {
  110. this.disposable.Dispose();
  111. }
  112. catch (Exception)
  113. {
  114. }
  115. }
  116. }
  117. }
  118. }