简单线程池实现v2版本
前不久实现的一个简单线程池:
http://www.cnblogs.com/ITAres/archive/2009/03/27/1423414.html
主是是通过记录线程的最后激活时间来判断线程是否超时。这次用WaitHandle对象来实现,感觉会合理一点。
代码比较简单,直接贴代码了。
ThreadPoolEx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using TopService.SysLog;
namespace TopService.ThreadEx
{
public class ThreadPoolEx
{
private WorkQueue _workQueue = new WorkQueue();
public int MaxThreadCount = 10;
public int MinThreadCount = 2;
private Hashtable _workerThreads = null;
private int _threadCount = 0;
private int _inUseWorkThread = 0;
private AutoResetEvent _waitHandle = new AutoResetEvent(false);
public int IdleTimeout = 20000;
public ThreadPoolEx()
: this(1, 1, 20000)
{
}
public ThreadPoolEx(int maxThreadCouont, int minThreadCount, int idleTimeout)
{
MaxThreadCount = maxThreadCouont;
MinThreadCount = minThreadCount;
IdleTimeout = idleTimeout;
_workerThreads = Hashtable.Synchronized(new Hashtable(MaxThreadCount));
}
public void EnqueueWorkItem(WaitCallback waitCallback, object objParams)
{
WorkItem workItem = new WorkItem()
{
WorkCallback = waitCallback,
ObjParams = objParams
};
_workQueue.Push(workItem);
_waitHandle.Set();
// If all the threads are busy then try to create a new one
if (_inUseWorkThread + WaitWorkItemCount > _workerThreads.Count)
{
StartThread();
}
}
private void StartThread()
{
if (_workerThreads.Count < MaxThreadCount)
{
Interlocked.Increment(ref _threadCount);
Thread thread = new Thread(ProcessWorkItems);
thread.IsBackground = true;
thread.Name = "ThreadPoolEx #" + _threadCount;
thread.Priority = ThreadPriority.Normal;
_workerThreads[thread] = System.DateTime.Now;
thread.Start();
}
}
private void ProcessWorkItems()
{
try
{
while (true)
{
WorkItem workItem = _workQueue.Pop();
if (workItem == null)
{
WaitHandle[] waitHandles = new WaitHandle[] { _waitHandle };
int index = WaitHandle.WaitAny(waitHandles, IdleTimeout,true);
bool success = (0 == index);
if (!success)
{
if (_workerThreads.Count > MinThreadCount)
{
_workerThreads.Remove(Thread.CurrentThread);
break;
}
continue;
}
workItem = _workQueue.Pop();
if (workItem == null) continue;
}
try
{
Interlocked.Increment(ref _inUseWorkThread);
workItem.Execute();
}
catch (Exception ex)
{
throw ex;
}
finally
{
Interlocked.Decrement(ref _inUseWorkThread);
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (_workerThreads.Contains(Thread.CurrentThread))
{
_workerThreads.Remove(Thread.CurrentThread);
}
}
}
public int WaitWorkItemCount
{
get
{
return _workQueue.WaitWorkItemCount;
}
}
public int TotalWorkItemCount
{
get
{
return _workQueue.TotalWorkItemCount;
}
}
public int ThreadCount
{
get
{
return _workerThreads.Count;
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using TopService.SysLog;
namespace TopService.ThreadEx
{
public class ThreadPoolEx
{
private WorkQueue _workQueue = new WorkQueue();
public int MaxThreadCount = 10;
public int MinThreadCount = 2;
private Hashtable _workerThreads = null;
private int _threadCount = 0;
private int _inUseWorkThread = 0;
private AutoResetEvent _waitHandle = new AutoResetEvent(false);
public int IdleTimeout = 20000;
public ThreadPoolEx()
: this(1, 1, 20000)
{
}
public ThreadPoolEx(int maxThreadCouont, int minThreadCount, int idleTimeout)
{
MaxThreadCount = maxThreadCouont;
MinThreadCount = minThreadCount;
IdleTimeout = idleTimeout;
_workerThreads = Hashtable.Synchronized(new Hashtable(MaxThreadCount));
}
public void EnqueueWorkItem(WaitCallback waitCallback, object objParams)
{
WorkItem workItem = new WorkItem()
{
WorkCallback = waitCallback,
ObjParams = objParams
};
_workQueue.Push(workItem);
_waitHandle.Set();
// If all the threads are busy then try to create a new one
if (_inUseWorkThread + WaitWorkItemCount > _workerThreads.Count)
{
StartThread();
}
}
private void StartThread()
{
if (_workerThreads.Count < MaxThreadCount)
{
Interlocked.Increment(ref _threadCount);
Thread thread = new Thread(ProcessWorkItems);
thread.IsBackground = true;
thread.Name = "ThreadPoolEx #" + _threadCount;
thread.Priority = ThreadPriority.Normal;
_workerThreads[thread] = System.DateTime.Now;
thread.Start();
}
}
private void ProcessWorkItems()
{
try
{
while (true)
{
WorkItem workItem = _workQueue.Pop();
if (workItem == null)
{
WaitHandle[] waitHandles = new WaitHandle[] { _waitHandle };
int index = WaitHandle.WaitAny(waitHandles, IdleTimeout,true);
bool success = (0 == index);
if (!success)
{
if (_workerThreads.Count > MinThreadCount)
{
_workerThreads.Remove(Thread.CurrentThread);
break;
}
continue;
}
workItem = _workQueue.Pop();
if (workItem == null) continue;
}
try
{
Interlocked.Increment(ref _inUseWorkThread);
workItem.Execute();
}
catch (Exception ex)
{
throw ex;
}
finally
{
Interlocked.Decrement(ref _inUseWorkThread);
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (_workerThreads.Contains(Thread.CurrentThread))
{
_workerThreads.Remove(Thread.CurrentThread);
}
}
}
public int WaitWorkItemCount
{
get
{
return _workQueue.WaitWorkItemCount;
}
}
public int TotalWorkItemCount
{
get
{
return _workQueue.TotalWorkItemCount;
}
}
public int ThreadCount
{
get
{
return _workerThreads.Count;
}
}
}
}
WorkQueue
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TopService.ThreadEx
{
public class WorkQueue
{
private static object threadLock = new object();
private Queue<WorkItem> _waitWorkQueue = new Queue<WorkItem>();
public WorkItem Pop()
{
lock (threadLock)
{
if (_waitWorkQueue.Count > 0)
{
return _waitWorkQueue.Dequeue();
}
return null;
}
}
public void Push(WorkItem workItem)
{
lock (threadLock)
{
++TotalWorkItemCount;
_waitWorkQueue.Enqueue(workItem);
}
}
public int WaitWorkItemCount
{
get
{
return _waitWorkQueue.Count;
}
}
public int TotalWorkItemCount = 0;
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TopService.ThreadEx
{
public class WorkQueue
{
private static object threadLock = new object();
private Queue<WorkItem> _waitWorkQueue = new Queue<WorkItem>();
public WorkItem Pop()
{
lock (threadLock)
{
if (_waitWorkQueue.Count > 0)
{
return _waitWorkQueue.Dequeue();
}
return null;
}
}
public void Push(WorkItem workItem)
{
lock (threadLock)
{
++TotalWorkItemCount;
_waitWorkQueue.Enqueue(workItem);
}
}
public int WaitWorkItemCount
{
get
{
return _waitWorkQueue.Count;
}
}
public int TotalWorkItemCount = 0;
}
}
WorkItem
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace TopService.ThreadEx
{
public class WorkItem
{
public WaitCallback WorkCallback;
public object ObjParams;
public void Execute()
{
WorkCallback(ObjParams);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace TopService.ThreadEx
{
public class WorkItem
{
public WaitCallback WorkCallback;
public object ObjParams;
public void Execute()
{
WorkCallback(ObjParams);
}
}
}