using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
namespace WindowsFormsApplication5
{
///
/// 并发测试
///
public class ConcurrentTest : IDisposable
{
#region 私有方法
///
/// 测试方法所在的接口
///
private Func func;
///
/// 主线程控制信号
///
private ManualResetEvent manualResetEvent;
///
/// 测试线程控制信号
///
private ManualResetEvent threadResetEvent;
///
/// 待执行的线程数
///
private List threads;
///
/// 测试结果
///
private List results;
///
/// 执行测试的成功数
///
private int successCount;
///
/// 执行测试的失败数
///
private int failureCount;
///
/// 测试耗时
///
private long elapsedMilliseconds;
///
/// 当前线程
///
private int currentIndex;
///
/// 当前测试的总线程数
///
private int currentCount;
///
/// 思考时间
///
private int thinkTime;
///
/// 重复次数
///
private int repeatCount;
///
/// 测试计时器
///
private Stopwatch stopwatch;
#endregion
#region 构造函数
///
/// 构造函数
///
public ConcurrentTest()
{
manualResetEvent = new ManualResetEvent(true);
threadResetEvent = new ManualResetEvent(true);
stopwatch = new Stopwatch();
}
#endregion
#region 执行测试
///
/// 执行多线程测试
///
/// 需要测试的线程数
/// 待执行方法
///
public List Execute(int threadCount, Func func)
{
return Execute(threadCount, 1, func);
}
///
/// 执行多线程测试
///
/// 需要测试的线程数
/// 重复次数
/// 待执行方法
///
public List Execute(int threadCount, int repeatCount, Func func)
{
return Execute(threadCount, 0, repeatCount, func);
}
///
/// 执行多线程测试
///
/// 需要测试的线程数
/// 思考时间,单位耗秒
/// 重复次数
/// 待执行方法
///
public List Execute(int threadCount, int thinkTime, int repeatCount, Func func)
{
return Execute(new List() { threadCount }, thinkTime, repeatCount, func);
}
///
/// 执行多线程测试
///
/// 分别需要测试的线程数
/// 思考时间,单位耗秒
/// 重复次数
/// 待执行方法
///
public List Execute(List threads, int thinkTime, int repeatCount, Func func)
{
this.func = func;
this.threads = threads;
this.thinkTime = thinkTime;
this.repeatCount = repeatCount;
CheckParameters();
CreateMultiThread();
return this.results;
}
#endregion
#region 验证参数
///
/// 验证参数
///
private void CheckParameters()
{
if (func == null) throw new ArgumentNullException("func不能为空");
if (threads == null || threads.Count == 0) throw new ArgumentNullException("threads不能为空或者长度不能为0");
if (thinkTime < 0) throw new Exception("thinkTime不能小于0");
if (repeatCount <= 0) throw new Exception("repeatCount不能小于等于0");
}
#endregion
#region 创建多线程并执行测试
///
/// 创建多线程进行测试
///
private void CreateMultiThread()
{
results = new List(threads.Count);
foreach (int threadCount in threads)
{
for (int repeat = 0; repeat < repeatCount; repeat++)
{
//主线程进入阻止状态
manualResetEvent.Reset();
//测试线程进入阻止状态
threadResetEvent.Reset();
stopwatch.Reset();
currentCount = threadCount;
currentIndex = 0;
successCount = 0;
failureCount = 0;
elapsedMilliseconds = 0;
for (int i = 0; i < currentCount; i++)
{
Thread t = new Thread(new ThreadStart(DoWork));
t.Start();
}
//阻止主线程,等待测试线程完成测试
manualResetEvent.WaitOne();
results.Add(new ConcurrentTestResult()
{
FailureCount = failureCount,
SuccessCount = successCount,
ElapsedMilliseconds = elapsedMilliseconds
});
Thread.Sleep(thinkTime);
}
}
}
///
/// 执行测试方法
///
private void DoWork()
{
bool executeResult;
Interlocked.Increment(ref currentIndex);
if (currentIndex < currentCount)
{
//等待所有线程创建完毕后同时执行测试
threadResetEvent.WaitOne();
}
else
{
//最后一个线程创建完成,通知所有线程,开始执行测试
threadResetEvent.Set();
//开始计时
stopwatch.Start();
}
//执行测试
executeResult = func();
Interlocked.Decrement(ref currentIndex);
if (currentIndex == 0)
{
//最后一个线程执行的测试结束,结束计时
stopwatch.Stop();
elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
//保存测试结果
if (executeResult)
Interlocked.Increment(ref successCount);
else
Interlocked.Increment(ref failureCount);
//通知主线程继续
manualResetEvent.Set();
}
else
{
//保存测试结果
if (executeResult)
Interlocked.Increment(ref successCount);
else
Interlocked.Increment(ref failureCount);
}
}
#endregion
#region 释放资源
///
/// 释放资源
///
public void Dispose()
{
manualResetEvent.Close();
threadResetEvent.Close();
}
#endregion
}
///
/// 并发测试结果
///
public class ConcurrentTestResult
{
///
/// 当前执行线程总数
///
public int ThreadCount
{
get { return SuccessCount + FailureCount; }
}
///
/// 测试成功数
///
public int SuccessCount { get; set; }
///
/// 测试失败数
///
public int FailureCount { get; set; }
///
/// 总耗时
///
public long ElapsedMilliseconds { get; set; }
}
}