有此时候我们需要大概计算一些过程在1秒中处理的数量,.net虽然提供了一些计时方法如Stopwatch计算代码运行所损耗的时间,但并没有提供每秒执行的计数.为了方便解决这种需要因此实现了一个简单秒计数器来完成这些功能,也顺便分享这样一个小小的类.
使用秒计数器
假设我们现在有两个线程处理方法,而方法里是不停地去处理一些东西,我们需要计算每个方法每秒处理的数量是多少可以这样做.
mCounter = new SecondCounter(); mTest1 = mCounter.Add("Test1"); mTest2 = mCounter.Add("Test2"); mCounter.Tick += (e) => { Console.WriteLine("{0}:{1}/s<{2}>",e.Name, e.Value, e.Count); }; mCounter.Open();
创建一个计数器,以上分别添加Test1和Test2计数器;然后设置计数器触发事件;以上代码是打印每一个计数项的信息,包括执行总次数和当前每秒执行的次数.相关信息设置完成后打开计数器即可.当计数器添加完成后就可以在方法中使用:
static void Test1(object state) { while (true) { mTest1.Add(1); System.Threading.Thread.Sleep(1); } } static void Test2(object state) { while (true) { mTest2.Add(1); System.Threading.Thread.Sleep(1); } }
下面通过不同线程调用这两个方法看一下计数次输出的情况:
System.Threading.ThreadPool.QueueUserWorkItem(Test1); System.Threading.ThreadPool.QueueUserWorkItem(Test2);
这样我们就可以非常简单的计算出每个方法每秒中大概执行的次数了,计数器还提供另一版本的Add(value)方法用于计算其他一些情况值,例如当前Socket接收的字节等.我们也可以用于计算一下数据库操作中每秒的操作次数.
mCounter = new SecondCounter(); mState = mCounter.Add("Smark.Data Query"); mCounter.Tick += (e) => { Console.WriteLine("{0}:{1}/s<{2}>", e.Name, e.Value, e.Count); }; mCounter.Open(); System.Threading.ThreadPool.QueueUserWorkItem(SmarkDataQuery); System.Threading.ThreadPool.QueueUserWorkItem(SmarkDataQuery); System.Threading.ThreadPool.QueueUserWorkItem(SmarkDataQuery); System.Threading.ThreadPool.QueueUserWorkItem(SmarkDataQuery); static void SmarkDataQuery(object state) { while (true) { Expression exp = new Expression(); (Order.orderID == exp.GetValues<Int32, Order>(Order.orderID, 2, 20)).List<Order>(); mState.Add(); } }
计数器完整代码
/// <summary> /// Copyright © henryfan 2012 /// Email: henryfan@msn.com /// HomePage: http://www.ikende.com /// CreateTime: 2012/10/27 21:56:05 /// </summary> public class SecondCounter:IDisposable { interface ICounter { void Process(); } public event Action<CounterItem> Tick; private List<CounterItem> mItems = new List<CounterItem>(); public class CounterItem : ICounter { private long mCount=0; private long mLastCount; public int Value { get; private set; } public string Name { get; set; } public void Add() { System.Threading.Interlocked.Increment(ref mCount); } public long Count { get { return mCount; } } public void Add(long value) { System.Threading.Interlocked.Add(ref mCount, value); } void ICounter.Process() { Value = (int)(mCount - mLastCount); mLastCount = mCount; } public override string ToString() { return string.Format("{0}:\t{1}/s", Name, Value); } } public CounterItem Add(string name) { CounterItem item = new CounterItem(); item.Name = name; mItems.Add(item); return item; } public void Open() { mTimer = new System.Threading.Timer(OnCallBack, this, 10, 980); } private void OnCallBack(object state) { for (int i = 0; i < mItems.Count; i++) { ((ICounter)mItems[i]).Process(); } try { if (Tick != null) { for (int i = 0; i < mItems.Count; i++) { Tick(mItems[i]); } } } catch { } } private System.Threading.Timer mTimer; private bool mIsDisposed = false; public void Dispose() { lock (this) { if (!mIsDisposed) { if (mTimer != null) mTimer.Dispose(); } } } }