134 lines
3.7 KiB
C#
134 lines
3.7 KiB
C#
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Diagnostics;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace FastGithub.Http
|
||
{
|
||
/// <summary>
|
||
/// 表示LifetimeHttpHandler清理器
|
||
/// </summary>
|
||
sealed class LifetimeHttpHandlerCleaner
|
||
{
|
||
/// <summary>
|
||
/// 当前监视生命周期的记录的数量
|
||
/// </summary>
|
||
private int trackingEntryCount = 0;
|
||
|
||
/// <summary>
|
||
/// 监视生命周期的记录队列
|
||
/// </summary>
|
||
private readonly ConcurrentQueue<TrackingEntry> trackingEntries = new();
|
||
|
||
/// <summary>
|
||
/// 获取或设置清理的时间间隔
|
||
/// 默认10s
|
||
/// </summary>
|
||
public TimeSpan CleanupInterval { get; set; } = TimeSpan.FromSeconds(10d);
|
||
|
||
/// <summary>
|
||
/// 添加要清除的httpHandler
|
||
/// </summary>
|
||
/// <param name="handler">httpHandler</param>
|
||
public void Add(LifetimeHttpHandler handler)
|
||
{
|
||
var entry = new TrackingEntry(handler);
|
||
this.trackingEntries.Enqueue(entry);
|
||
|
||
// 从0变为1,要启动清理作业
|
||
if (Interlocked.Increment(ref this.trackingEntryCount) == 1)
|
||
{
|
||
this.StartCleanup();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启动清理作业
|
||
/// </summary>
|
||
private async void StartCleanup()
|
||
{
|
||
await Task.Yield();
|
||
while (this.Cleanup() == false)
|
||
{
|
||
await Task.Delay(this.CleanupInterval);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清理失效的拦截器
|
||
/// 返回是否完全清理
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private bool Cleanup()
|
||
{
|
||
var cleanCount = this.trackingEntries.Count;
|
||
for (var i = 0; i < cleanCount; i++)
|
||
{
|
||
this.trackingEntries.TryDequeue(out var entry);
|
||
Debug.Assert(entry != null);
|
||
|
||
if (entry.CanDispose == false)
|
||
{
|
||
this.trackingEntries.Enqueue(entry);
|
||
continue;
|
||
}
|
||
|
||
entry.Dispose();
|
||
if (Interlocked.Decrement(ref this.trackingEntryCount) == 0)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 表示监视生命周期的记录
|
||
/// </summary>
|
||
private class TrackingEntry : IDisposable
|
||
{
|
||
/// <summary>
|
||
/// 用于释放资源的对象
|
||
/// </summary>
|
||
private readonly IDisposable disposable;
|
||
|
||
/// <summary>
|
||
/// 监视对象的弱引用
|
||
/// </summary>
|
||
private readonly WeakReference weakReference;
|
||
|
||
/// <summary>
|
||
/// 获取是否可以释放资源
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public bool CanDispose => this.weakReference.IsAlive == false;
|
||
|
||
/// <summary>
|
||
/// 监视生命周期的记录
|
||
/// </summary>
|
||
/// <param name="handler">激活状态的httpHandler</param>
|
||
public TrackingEntry(LifetimeHttpHandler handler)
|
||
{
|
||
this.disposable = handler.InnerHandler!;
|
||
this.weakReference = new WeakReference(handler);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放资源
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
try
|
||
{
|
||
this.disposable.Dispose();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|