commit 8ae7233a588dafd7873130e1aee752eb9431ecc3
Author: falcon <9504402@qq.com>
Date: Thu Apr 25 17:03:09 2019 +0800
Init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..22243cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,266 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+.vs/
+
+#Log files
+HosManager/Logs/
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
\ No newline at end of file
diff --git a/QueueTokenBucketTest/Program.cs b/QueueTokenBucketTest/Program.cs
new file mode 100644
index 0000000..728e4a0
--- /dev/null
+++ b/QueueTokenBucketTest/Program.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using TokenBucketLib;
+using System.Threading;
+
+namespace QueueTokenBucketTest
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var qtb = new QueueTokenBucket()
+ {
+ //QueueMaxLenth = 20,
+ IR = 5,
+ BS = 10,
+ };
+ qtb.SetFullPass();
+ qtb.GetTokenEnd += (sender, e) =>
+ {
+ Console.WriteLine("at {2}:{3} {0} S:{1}", e.Pass.Requester, e.Pass.State.ToString(), DateTime.Now.Minute, DateTime.Now.Second);
+ };
+
+ qtb.Start();
+
+
+ for (int i = 0; i < 40; i++)
+ {
+ Console.WriteLine("at {1}:{2} Request{0} ", i, DateTime.Now.Minute, DateTime.Now.Second);
+ qtb.GetTokenAsyn(i);
+ //Thread.Sleep(500);
+ }
+ Console.ReadKey();
+ qtb.Dispose();
+ }
+ }
+}
diff --git a/QueueTokenBucketTest/Properties/AssemblyInfo.cs b/QueueTokenBucketTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ed192b0
--- /dev/null
+++ b/QueueTokenBucketTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("QueueTokenBucketTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("WwW.YlmF.CoM")]
+[assembly: AssemblyProduct("QueueTokenBucketTest")]
+[assembly: AssemblyCopyright("Copyright © WwW.YlmF.CoM 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("8025223b-d94a-4e90-8c57-95a09a01eed7")]
+
+// 程序集的版本信息由下面四个值组成:
+//
+// 主版本
+// 次版本
+// 内部版本号
+// 修订号
+//
+// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/QueueTokenBucketTest/QueueTokenBucketTest.csproj b/QueueTokenBucketTest/QueueTokenBucketTest.csproj
new file mode 100644
index 0000000..c0e7e27
--- /dev/null
+++ b/QueueTokenBucketTest/QueueTokenBucketTest.csproj
@@ -0,0 +1,63 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}
+ Exe
+ Properties
+ QueueTokenBucketTest
+ QueueTokenBucketTest
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}
+ TokenBucketLib
+
+
+
+
+
\ No newline at end of file
diff --git a/TokenBucket.sln b/TokenBucket.sln
new file mode 100644
index 0000000..862b49a
--- /dev/null
+++ b/TokenBucket.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TokenBucketLib", "TokenBucketLib\TokenBucketLib.csproj", "{4F0E1500-FACA-4C5C-972D-680D251EA6AA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TokenBucketTest", "TokenBucketTest\TokenBucketTest.csproj", "{EF1E13ED-0A5B-426F-9835-590121E8D48C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QueueTokenBucketTest", "QueueTokenBucketTest\QueueTokenBucketTest.csproj", "{51BE6E70-6F48-4409-B212-DC245FC1EFD5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}.Release|x86.ActiveCfg = Release|Any CPU
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Debug|x86.ActiveCfg = Debug|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Debug|x86.Build.0 = Debug|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Release|Any CPU.ActiveCfg = Release|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Release|Mixed Platforms.Build.0 = Release|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Release|x86.ActiveCfg = Release|x86
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}.Release|x86.Build.0 = Release|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Debug|x86.ActiveCfg = Debug|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Debug|x86.Build.0 = Debug|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Release|Any CPU.ActiveCfg = Release|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Release|Mixed Platforms.Build.0 = Release|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Release|x86.ActiveCfg = Release|x86
+ {51BE6E70-6F48-4409-B212-DC245FC1EFD5}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TokenBucketLib/Properties/AssemblyInfo.cs b/TokenBucketLib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8708a8d
--- /dev/null
+++ b/TokenBucketLib/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("TokenBucketLib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("WwW.YlmF.CoM")]
+[assembly: AssemblyProduct("TokenBucketLib")]
+[assembly: AssemblyCopyright("Copyright © WwW.YlmF.CoM 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("a79ebfdd-2ac8-4388-9973-16bd1bc98d00")]
+
+// 程序集的版本信息由下面四个值组成:
+//
+// 主版本
+// 次版本
+// 内部版本号
+// 修订号
+//
+// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TokenBucketLib/QueueTokenBuket.cs b/TokenBucketLib/QueueTokenBuket.cs
new file mode 100644
index 0000000..dab1e49
--- /dev/null
+++ b/TokenBucketLib/QueueTokenBuket.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TokenBucketLib
+{
+ ///
+ /// 队列令牌桶
+ /// 资源请求首先到达令牌桶,如果获得令牌马上返回,如果失败将进入等待队列,等待获得令牌后返回,或者令牌桶满后获取失败并丢弃。
+ ///
+ public class QueueTokenBucket : TokenBucket
+ {
+ ///
+ /// 最大缓冲对列数。-1为不限长度。
+ ///
+ public int QueueMaxLenth { get; set; }
+
+ private Queue queue;
+ private readonly static object objlock = new object();
+
+ ///
+ /// 构造一个带缓冲队列的令牌桶
+ ///
+ public QueueTokenBucket()
+ : this(-1)
+ {
+ }
+
+ ///
+ /// 通过提供最大缓冲队列数构造缓冲队列令牌桶
+ ///
+ /// 缓冲区大小。-1为不限制大小。
+ public QueueTokenBucket(int queueMaxLenth)
+ {
+ QueueMaxLenth = queueMaxLenth;
+ queue = new Queue();
+ base.Put += new Action(QueueTokenBuket_Put);
+ }
+
+ private void QueueTokenBuket_Put(TokenBucket obj)
+ {
+ if (queue.Count > 0)
+ {
+ lock (objlock)
+ {
+ var c = queue.Count;
+ for (int i = 0; i < c; i++)
+ {
+ var r = base.GetToken();
+ if (r.State == TokenBucketPassEnum.passed)
+ {
+ TokenBucketPass result = queue.Dequeue();
+ result.State = TokenBucketPassEnum.passed;
+ if (GetTokenEnd != null) GetTokenEnd(this, new TokenBucketEventArgs(result));
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ public event Action GetTokenEnd;
+
+ ///
+ /// 开始异步获取令牌
+ ///
+ /// 异步传入的对象,这个对象会随TokenBucketPass.Requester传出。
+ public void GetTokenAsyn(object requester)
+ {
+ var result = new TokenBucketPass();
+ result.Requester = requester;
+ var r = base.GetToken();
+ if (r.State == TokenBucketPassEnum.passed)
+ {
+ result.State = r.State;
+ if (GetTokenEnd != null) GetTokenEnd(this, new TokenBucketEventArgs(result));
+ }
+ else
+ {
+ if (QueueMaxLenth != -1 && QueueMaxLenth < queue.Count)
+ {
+ result.State = TokenBucketPassEnum.losted;
+ GetTokenEnd(this, new TokenBucketEventArgs(result));
+ }
+ else
+ {
+ queue.Enqueue(result);
+ }
+ }
+ }
+
+ #region IDisposable 成员
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ queue.Clear();
+ }
+ base.Dispose(disposing);
+ }
+ #endregion
+
+ }
+}
diff --git a/TokenBucketLib/TokenBucket.cs b/TokenBucketLib/TokenBucket.cs
new file mode 100644
index 0000000..fe09107
--- /dev/null
+++ b/TokenBucketLib/TokenBucket.cs
@@ -0,0 +1,227 @@
+using System;
+using System.Threading;
+
+namespace TokenBucketLib
+{
+ /// 令牌桶
+ public class TokenBucket : IDisposable
+ {
+ #region 公开属性
+ ///
+ /// 令牌投入速率
+ ///
+ public int IR { get; set; }
+
+ private int _BS;
+ ///
+ /// 令牌上限
+ ///
+ public int BS
+ {
+ get
+ {
+ return _BS;
+ }
+ set
+ {
+ _BS = value;
+ if (CurCount > value)
+ {
+ CurCount = value;
+ }
+ }
+ }
+
+ ///
+ /// 令牌桶是否在运行
+ ///
+ public bool Runing { get; set; }
+
+ ///
+ /// 当前剩余令牌数
+ ///
+ public int CurCount { get; private set; }
+
+ #endregion
+
+ #region 私有字段
+ ///
+ /// 添加令牌的计时器
+ ///
+ private Timer timer;
+
+ ///
+ /// 共享锁
+ ///
+ protected static readonly object lockkey = new object();
+ #endregion
+
+ #region 事件
+
+ ///
+ /// 添加令牌完成事件
+ ///
+ public event Action Put;
+
+ #endregion
+
+ #region 构造
+ ///
+ /// 默认构造,速率100,上限1000
+ ///
+ public TokenBucket()
+ : this(100, 1000, 1000)
+ {
+ }
+
+ ///
+ /// 通过指定速率和上限构造令牌桶
+ ///
+ /// 投入速率
+ /// 令牌上限
+ /// 初始令牌数量
+ public TokenBucket(int ir, int bs, int ip)
+ {
+ IR = ir; BS = bs; CurCount = ip;
+ Runing = false;
+ }
+ #endregion
+
+ #region 公开方法
+
+ ///
+ /// 令牌桶开始工作
+ ///
+ 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);
+ }
+ }
+
+ ///
+ /// 令牌桶停止工作
+ ///
+ public virtual void Stop()
+ {
+ if (timer != null)
+ {
+ timer.Dispose();
+ timer = null;
+ }
+ Runing = false;
+ }
+
+ ///
+ /// 设置令牌桶满令牌
+ ///
+ public void SetFullPass()
+ {
+ CurCount = BS;
+ }
+
+ ///
+ /// 清空令牌桶
+ ///
+ public void ClearPass()
+ {
+ CurCount = 0;
+ }
+
+ ///
+ /// 获得一块令牌
+ ///
+ ///
+ 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 私有方法
+
+ ///
+ /// 向令牌桶添加令牌
+ ///
+ ///
+ 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
+ }
+}
diff --git a/TokenBucketLib/TokenBucketEventArgs.cs b/TokenBucketLib/TokenBucketEventArgs.cs
new file mode 100644
index 0000000..5b6c619
--- /dev/null
+++ b/TokenBucketLib/TokenBucketEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TokenBucketLib
+{
+ public class TokenBucketEventArgs : EventArgs
+ {
+ public TokenBucketEventArgs(TokenBucketPass pass)
+ {
+ Pass = pass;
+ }
+ public TokenBucketPass Pass { get; set; }
+ }
+}
diff --git a/TokenBucketLib/TokenBucketFactory.cs b/TokenBucketLib/TokenBucketFactory.cs
new file mode 100644
index 0000000..176f139
--- /dev/null
+++ b/TokenBucketLib/TokenBucketFactory.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TokenBucketLib
+{
+ ///
+ /// 令牌桶工厂,用来生成令牌桶
+ ///
+ public static class TokenBucketFactory
+ {
+ ///
+ /// 制造一个令牌桶
+ ///
+ /// 令牌投放速度
+ /// 令牌上限
+ /// 初始令牌数
+ /// 一个令牌桶
+ public static TokenBucket Buid(int ir, int bs, int ip)
+ {
+ return new TokenBucket(ir, bs, ip > bs ? bs : ip);
+ }
+
+ public static QueueTokenBucket BuidQueueTokenBucket()
+ {
+ return new QueueTokenBucket();
+ }
+ }
+}
diff --git a/TokenBucketLib/TokenBucketLib.csproj b/TokenBucketLib/TokenBucketLib.csproj
new file mode 100644
index 0000000..0bb5a9d
--- /dev/null
+++ b/TokenBucketLib/TokenBucketLib.csproj
@@ -0,0 +1,55 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}
+ Library
+ Properties
+ TokenBucketLib
+ TokenBucketLib
+ v4.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TokenBucketLib/TokenBucketPass.cs b/TokenBucketLib/TokenBucketPass.cs
new file mode 100644
index 0000000..7760213
--- /dev/null
+++ b/TokenBucketLib/TokenBucketPass.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+
+namespace TokenBucketLib
+{
+ ///
+ /// 票据
+ ///
+ public class TokenBucketPass
+ {
+ ///
+ /// 票据状态
+ ///
+ public TokenBucketPassEnum State { get; set; }
+
+ ///
+ /// 令牌请求者。
+ ///
+ public object Requester { get; set; }
+
+ ///
+ /// 令牌桶工作期间包含的错误信息。
+ ///
+ public Queue errs { get; set; }
+ }
+}
diff --git a/TokenBucketLib/TokenBucketPassEnum.cs b/TokenBucketLib/TokenBucketPassEnum.cs
new file mode 100644
index 0000000..4c4b57e
--- /dev/null
+++ b/TokenBucketLib/TokenBucketPassEnum.cs
@@ -0,0 +1,31 @@
+
+namespace TokenBucketLib
+{
+ public enum TokenBucketPassEnum
+ {
+ ///
+ /// 通过,获得票据
+ ///
+ passed = 0,
+
+ ///
+ /// 未获得票据
+ ///
+ unpassed = 1,
+
+ ///
+ /// 被丢弃
+ ///
+ losted = 2,
+
+ ///
+ /// 超时,目前不支持
+ ///
+ timeOut = 3,
+
+ ///
+ /// 令牌桶未开始运行
+ ///
+ TokenBucketNotRun = 1000,
+ }
+}
diff --git a/TokenBucketTest/Program.cs b/TokenBucketTest/Program.cs
new file mode 100644
index 0000000..09ca6ef
--- /dev/null
+++ b/TokenBucketTest/Program.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using TokenBucketLib;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace TokenBucketTest
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ TokenBucket tb = TokenBucketFactory.Buid(2, 10, 10);
+ tb.Put += new Action(tb_Put);
+ tb.Start();
+ Thread.Sleep(1000);
+ Task t1 = Task.Factory.StartNew(() => Consumer(tb, 1));
+ Task t2 = Task.Factory.StartNew(() => Consumer(tb, 2));
+ Thread.Sleep(2000);
+
+ t2.Wait();
+ t1.Wait();
+ }
+
+ static void Consumer(TokenBucket tb, int taskid)
+ {
+ for (int i = 0; i < 20; i++)
+ {
+ Thread.Sleep(200);
+ var pass = tb.GetToken();
+ Console.WriteLine("task{2} 请求令牌 Cur:{1} Res:{0}", pass.State.ToString(), tb.CurCount, taskid);
+ }
+ }
+
+ static void tb_Put(TokenBucket arg)
+ {
+ Console.WriteLine("添加令牌 Cur:{0} Max:{1}", arg.CurCount, arg.BS);
+ }
+ }
+}
diff --git a/TokenBucketTest/Properties/AssemblyInfo.cs b/TokenBucketTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ca3636d
--- /dev/null
+++ b/TokenBucketTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("TokenBucketTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("WwW.YlmF.CoM")]
+[assembly: AssemblyProduct("TokenBucketTest")]
+[assembly: AssemblyCopyright("Copyright © WwW.YlmF.CoM 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("4f946987-cff5-424d-8b83-3830656009ed")]
+
+// 程序集的版本信息由下面四个值组成:
+//
+// 主版本
+// 次版本
+// 内部版本号
+// 修订号
+//
+// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TokenBucketTest/TokenBucketTest.csproj b/TokenBucketTest/TokenBucketTest.csproj
new file mode 100644
index 0000000..1e7f8c1
--- /dev/null
+++ b/TokenBucketTest/TokenBucketTest.csproj
@@ -0,0 +1,61 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {EF1E13ED-0A5B-426F-9835-590121E8D48C}
+ Exe
+ Properties
+ TokenBucketTest
+ TokenBucketTest
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {4F0E1500-FACA-4C5C-972D-680D251EA6AA}
+ TokenBucketLib
+
+
+
+
+
\ No newline at end of file