前不久实现的一个简单线程池:
http://www.cnblogs.com/ITAres/archive/2009/03/27/1423414.html
主是是通过记录线程的最后激活时间来判断线程是否超时。这次用WaitHandle对象来实现,感觉会合理一点。
代码比较简单,直接贴代码了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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;
}
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 ;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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);
}
}
}