TokenBucket/TokenBucketLib/TokenBucket.cs
2019-04-25 17:03:09 +08:00

228 lines
5.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Threading;
namespace TokenBucketLib
{
/// <summary>令牌桶</summary>
public class TokenBucket : IDisposable
{
#region
/// <summary>
/// 令牌投入速率
/// </summary>
public int IR { get; set; }
private int _BS;
/// <summary>
/// 令牌上限
/// </summary>
public int BS
{
get
{
return _BS;
}
set
{
_BS = value;
if (CurCount > value)
{
CurCount = value;
}
}
}
/// <summary>
/// 令牌桶是否在运行
/// </summary>
public bool Runing { get; set; }
/// <summary>
/// 当前剩余令牌数
/// </summary>
public int CurCount { get; private set; }
#endregion
#region
/// <summary>
/// 添加令牌的计时器
/// </summary>
private Timer timer;
/// <summary>
/// 共享锁
/// </summary>
protected static readonly object lockkey = new object();
#endregion
#region
/// <summary>
/// 添加令牌完成事件
/// </summary>
public event Action<TokenBucket> Put;
#endregion
#region
/// <summary>
/// 默认构造速率100上限1000
/// </summary>
public TokenBucket()
: this(100, 1000, 1000)
{
}
/// <summary>
/// 通过指定速率和上限构造令牌桶
/// </summary>
/// <param name="ir">投入速率</param>
/// <param name="bs">令牌上限</param>
/// <param name="ip">初始令牌数量</param>
public TokenBucket(int ir, int bs, int ip)
{
IR = ir; BS = bs; CurCount = ip;
Runing = false;
}
#endregion
#region
/// <summary>
/// 令牌桶开始工作
/// </summary>
public virtual void Start()
{
try
{
timer = new Timer(PutToken, null, 1000, 1000);
Runing = true;
}
catch (Exception ex)
{
Runing = false;
throw new Exception("TokenBucket start err!", ex);
}
}
/// <summary>
/// 令牌桶停止工作
/// </summary>
public virtual void Stop()
{
if (timer != null)
{
timer.Dispose();
timer = null;
}
Runing = false;
}
/// <summary>
/// 设置令牌桶满令牌
/// </summary>
public void SetFullPass()
{
CurCount = BS;
}
/// <summary>
/// 清空令牌桶
/// </summary>
public void ClearPass()
{
CurCount = 0;
}
/// <summary>
/// 获得一块令牌
/// </summary>
/// <returns></returns>
public virtual TokenBucketPass GetToken()
{
TokenBucketPass tbr = new TokenBucketPass();
if (!Runing)
{
tbr.State = TokenBucketPassEnum.TokenBucketNotRun;
}
else
{
lock (lockkey)
{
//Console.WriteLine("s");
//Console.WriteLine(CurCount);
if (CurCount <= 0)
{
tbr.State = TokenBucketPassEnum.unpassed;
}
else
{
CurCount--;
tbr.State = TokenBucketPassEnum.passed;
}
//Console.WriteLine("e");
}
}
return tbr;
}
#endregion
#region
/// <summary>
/// 向令牌桶添加令牌
/// </summary>
/// <param name="obj"></param>
protected void PutToken(object obj)
{
if (BS == CurCount) return;
lock (lockkey)
{
CurCount += IR;
if (CurCount > BS)
{
CurCount = BS;
}
}
if (Put != null) Put(this);
}
#endregion
#region IDisposable
private bool IsDisposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed)
{
//释放托管资源
if (disposing)
{
if (timer != null)
{
timer.Dispose();
timer = null;
}
}
//释放非托管资源
}
IsDisposed = true;
}
~TokenBucket()
{
Dispose(false);
}
#endregion
}
}