由于需求变化,今天临时写了一个“令牌桶”类。他的功能是:存放令牌并管理令牌的过期时间
不多说了直接上代码:
public class TokenBucket { /// <summary> /// 令牌过期时间 /// 默认60秒 /// </summary> public int TokenTimeOutTrick { get; set; } = 60000; private readonly ConcurrentDictionary<string, CancellationTokenSource> buket = new ConcurrentDictionary<string, CancellationTokenSource>(); /// <summary> /// 添加令牌 /// </summary> /// <param name="token"></param> /// <returns></returns> public bool AddToken(string token) { CancellationTokenSource tokenSource = new CancellationTokenSource(); var result = buket.TryAdd(token, tokenSource); if (result) { #pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 TokenTimeOut(token, tokenSource); #pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 } return result; } /// <summary> /// 令牌过期 /// </summary> /// <param name="token"></param> /// <param name="tokenSource"></param> /// <returns></returns> private async Task TokenTimeOut(string token, CancellationTokenSource tokenSource) { CancellationToken cancellationToken = tokenSource.Token; await Task.Delay(TokenTimeOutTrick, cancellationToken); buket.TryRemove(token, out CancellationTokenSource cts); if (cts != null) cts.Dispose(); } /// <summary> /// 删除令牌 /// </summary> /// <param name="token"></param> public void ReomveToken(string token) { var remove = buket.TryRemove(token, out CancellationTokenSource cts); try { if (remove) { cts.Cancel(); } } catch { } finally { if (cts != null) cts.Dispose(); } } /// <summary> /// 令牌是否存在 /// </summary> /// <param name="token"></param> /// <returns></returns> public bool HasToken(string token) { return buket.ContainsKey(token); } }