1、在C#中,不用去面对完成端口的操作系统内核对象,Microsoft已经为我们提供了SocketAsyncEventArgs类,它封装了IOCP的使用。请参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1。
2、我的SocketAsyncEventArgsPool类使用List对象来存储对客户端来通信的SocketAsyncEventArgs对象,它相当于直接使用内核对象时的IoContext。我这样设计比用堆栈来实现的好处理是,我可以在SocketAsyncEventArgsPool池中找到任何一个与服务器连接的客户,主动向它发信息。而用堆栈来实现的话,要主动给客户发信息,则还要设计一个结构来存储已连接上服务器的客户。
3、对每一个客户端不管还发送还是接收,我使用同一个SocketAsyncEventArgs对象,对每一个客户端来说,通信是同步进行的,也就是说服务器高度保证同一个客户连接上要么在投递发送请求,并等待;或者是在投递接收请求,等待中。本例只做echo服务器,还未考虑由服务器主动向客户发送信息。
4、SocketAsyncEventArgs的UserToken被直接设定为被接受的客户端Socket。
5、没有使用BufferManager 类,因为我在初始化时给每一个SocketAsyncEventArgsPool中的对象分配一个缓冲区,发送时使用Arrary.Copy来进行字符拷贝,不去改变缓冲区的位置,只改变使用的长度,因此在下次投递接收请求时恢复缓冲区长度就可以了!如果要主动给客户发信息的话,可以new一个SocketAsyncEventArgs对象,或者在初始化中建立几个来专门用于主动发送信息,因为这种需求一般是进行信息群发,建立一个对象可以用于很多次信息发送,总体来看,这种花销不大,还减去了字符拷贝和消耗。
demo下载地址: http://files.cnblogs.com/files/airtcp/IocpServer.zip
2、我的SocketAsyncEventArgsPool类使用List对象来存储对客户端来通信的SocketAsyncEventArgs对象,它相当于直接使用内核对象时的IoContext。我这样设计比用堆栈来实现的好处理是,我可以在SocketAsyncEventArgsPool池中找到任何一个与服务器连接的客户,主动向它发信息。而用堆栈来实现的话,要主动给客户发信息,则还要设计一个结构来存储已连接上服务器的客户。
3、对每一个客户端不管还发送还是接收,我使用同一个SocketAsyncEventArgs对象,对每一个客户端来说,通信是同步进行的,也就是说服务器高度保证同一个客户连接上要么在投递发送请求,并等待;或者是在投递接收请求,等待中。本例只做echo服务器,还未考虑由服务器主动向客户发送信息。
4、SocketAsyncEventArgs的UserToken被直接设定为被接受的客户端Socket。
5、没有使用BufferManager 类,因为我在初始化时给每一个SocketAsyncEventArgsPool中的对象分配一个缓冲区,发送时使用Arrary.Copy来进行字符拷贝,不去改变缓冲区的位置,只改变使用的长度,因此在下次投递接收请求时恢复缓冲区长度就可以了!如果要主动给客户发信息的话,可以new一个SocketAsyncEventArgs对象,或者在初始化中建立几个来专门用于主动发送信息,因为这种需求一般是进行信息群发,建立一个对象可以用于很多次信息发送,总体来看,这种花销不大,还减去了字符拷贝和消耗。
demo下载地址: http://files.cnblogs.com/files/airtcp/IocpServer.zip
经典代码IOCP(完成端口)的C#.Net实现----解读
感谢原作者
重复造轮子的意义在于深刻的理解和学习---
main.cs:
- /*using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace c2iocp
- {
- class Program
- {
- static void Main(string[] args)
- {
- }
- }
- }
- */
- using System;
- using System.Threading; // Included for the Thread.Sleep call
- using Continuum.Threading;
- namespace Sample
- {
- //============================================
- /// <summary> Sample class for the threading class </summary>
- public class UtilThreadingSample
- {
- //*******************************************
- /// <summary> Test Method </summary>
- static void Main()
- {
- // Create the MSSQL IOCP Thread Pool
- IOCPThreadPool pThreadPool = new IOCPThreadPool(0, 5, 10, new IOCPThreadPool.USER_FUNCTION(IOCPThreadFunction));
- pThreadPool.PostEvent(10);
- Thread.Sleep(10000);
- pThreadPool.Dispose();
- }
- //*****************************************
- /// <summary> Function to be called by the IOCP thread pool. Called when
- /// a command is posted for processing by the SocketManager </summary>
- /// <param name="iValue"> The value provided by the thread posting the event </param>
- static public void IOCPThreadFunction(Int32 iValue)
- {
- try
- {
- Console.WriteLine("Value: {0}", iValue);
- }
- catch (Exception pException)
- {
- Console.WriteLine(pException.Message);
- }
- }
- }
- }
/*using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace c2iocp
{
class Program
{
static void Main(string[] args)
{
}
}
}
*/
using System;
using System.Threading; // Included for the Thread.Sleep call
using Continuum.Threading;
namespace Sample
{
//============================================
/// <summary> Sample class for the threading class </summary>
public class UtilThreadingSample
{
//*******************************************
/// <summary> Test Method </summary>
static void Main()
{
// Create the MSSQL IOCP Thread Pool
IOCPThreadPool pThreadPool = new IOCPThreadPool(0, 5, 10, new IOCPThreadPool.USER_FUNCTION(IOCPThreadFunction));
pThreadPool.PostEvent(10);
Thread.Sleep(10000);
pThreadPool.Dispose();
}
//*****************************************
/// <summary> Function to be called by the IOCP thread pool. Called when
/// a command is posted for processing by the SocketManager </summary>
/// <param name="iValue"> The value provided by the thread posting the event </param>
static public void IOCPThreadFunction(Int32 iValue)
{
try
{
Console.WriteLine("Value: {0}", iValue);
}
catch (Exception pException)
{
Console.WriteLine(pException.Message);
}
}
}
}
continuum.cs
- using System;
- using System.Threading;
- using System.Runtime.InteropServices;
- namespace Continuum.Threading
- {
- // Structures
- //==========================================
- /// <summary> This is the WIN32 OVERLAPPED structure </summary>
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public unsafe struct OVERLAPPED
- {
- UInt32* ulpInternal;
- UInt32* ulpInternalHigh;
- Int32 lOffset;
- Int32 lOffsetHigh;
- UInt32 hEvent;
- }
- // Classes
- //============================================
- /// <summary> This class provides the ability to create a thread pool to manage work. The
- /// class abstracts the Win32 IOCompletionPort API so it requires the use of
- /// unmanaged code. Unfortunately the .NET framework does not provide this functionality </summary>
- public sealed class IOCPThreadPool
- {
- // Win32 Function Prototypes
- /// <summary> Win32Func: Create an IO Completion Port Thread Pool </summary>
- [DllImport("Kernel32", CharSet = CharSet.Auto)]
- private unsafe static extern UInt32 CreateIoCompletionPort(UInt32 hFile, UInt32 hExistingCompletionPort, UInt32* puiCompletionKey, UInt32 uiNumberOfConcurrentThreads);
- /// <summary> Win32Func: Closes an IO Completion Port Thread Pool </summary>
- [DllImport("Kernel32", CharSet = CharSet.Auto)]
- private unsafe static extern Boolean CloseHandle(UInt32 hObject);
- /// <summary> Win32Func: Posts a context based event into an IO Completion Port Thread Pool </summary>
- [DllImport("Kernel32", CharSet = CharSet.Auto)]
- private unsafe static extern Boolean PostQueuedCompletionStatus(UInt32 hCompletionPort, UInt32 uiSizeOfArgument, UInt32* puiUserArg, OVERLAPPED* pOverlapped);
- /// <summary> Win32Func: Waits on a context based event from an IO Completion Port Thread Pool.
- /// All threads in the pool wait in this Win32 Function </summary>
- [DllImport("Kernel32", CharSet = CharSet.Auto)]
- private unsafe static extern Boolean GetQueuedCompletionStatus(UInt32 hCompletionPort, UInt32* pSizeOfArgument, UInt32* puiUserArg, OVERLAPPED** ppOverlapped, UInt32 uiMilliseconds);
- // Constants
- /// <summary> SimTypeConst: This represents the Win32 Invalid Handle Value Macro </summary>
- private const UInt32 INVALID_HANDLE_VALUE = 0xffffffff;
- /// <summary> SimTypeConst: This represents the Win32 INFINITE Macro </summary>
- private const UInt32 INIFINITE = 0xffffffff;
- /// <summary> SimTypeConst: This tells the IOCP Function to shutdown </summary>
- private const Int32 SHUTDOWN_IOCPTHREAD = 0x7fffffff;
- // Delegate Function Types
- /// <summary> DelType: This is the type of user function to be supplied for the thread pool </summary>
- public delegate void USER_FUNCTION(Int32 iValue);
- // Private Properties
- private UInt32 m_hHandle;
- /// <summary> SimType: Contains the IO Completion Port Thread Pool handle for this instance </summary>
- private UInt32 GetHandle { get { return m_hHandle; } set { m_hHandle = value; } }
- private Int32 m_uiMaxConcurrency;
- /// <summary> SimType: The maximum number of threads that may be running at the same time </summary>
- private Int32 GetMaxConcurrency { get { return m_uiMaxConcurrency; } set { m_uiMaxConcurrency = value; } }
- private Int32 m_iMinThreadsInPool;
- /// <summary> SimType: The minimal number of threads the thread pool maintains </summary>
- private Int32 GetMinThreadsInPool { get { return m_iMinThreadsInPool; } set { m_iMinThreadsInPool = value; } }
- private Int32 m_iMaxThreadsInPool;
- /// <summary> SimType: The maximum number of threads the thread pool maintains </summary>
- private Int32 GetMaxThreadsInPool { get { return m_iMaxThreadsInPool; } set { m_iMaxThreadsInPool = value; } }
- private Object m_pCriticalSection;
- /// <summary> RefType: A serialization object to protect the class state </summary>
- private Object GetCriticalSection { get { return m_pCriticalSection; } set { m_pCriticalSection = value; } }
- private USER_FUNCTION m_pfnUserFunction;
- /// <summary> DelType: A reference to a user specified function to be call by the thread pool </summary>
- private USER_FUNCTION GetUserFunction { get { return m_pfnUserFunction; } set { m_pfnUserFunction = value; } }
- private Boolean m_bDisposeFlag;
- /// <summary> SimType: Flag to indicate if the class is disposing </summary>
- private Boolean IsDisposed { get { return m_bDisposeFlag; } set { m_bDisposeFlag = value; } }
- // Public Properties
- private Int32 m_iCurThreadsInPool;
- /// <summary> SimType: The current number of threads in the thread pool </summary>
- public Int32 GetCurThreadsInPool { get { return m_iCurThreadsInPool; } set { m_iCurThreadsInPool = value; } }
- /// <summary> SimType: Increment current number of threads in the thread pool </summary>
- private Int32 IncCurThreadsInPool() { return Interlocked.Increment(ref m_iCurThreadsInPool); }
- /// <summary> SimType: Decrement current number of threads in the thread pool </summary>
- private Int32 DecCurThreadsInPool() { return Interlocked.Decrement(ref m_iCurThreadsInPool); }
- private Int32 m_iActThreadsInPool;
- /// <summary> SimType: The current number of active threads in the thread pool </summary>
- public Int32 GetActThreadsInPool { get { return m_iActThreadsInPool; } set { m_iActThreadsInPool = value; } }
- /// <summary> SimType: Increment current number of active threads in the thread pool </summary>
- private Int32 IncActThreadsInPool() { return Interlocked.Increment(ref m_iActThreadsInPool); }
- /// <summary> SimType: Decrement current number of active threads in the thread pool </summary>
- private Int32 DecActThreadsInPool() { return Interlocked.Decrement(ref m_iActThreadsInPool); }
- private Int32 m_iCurWorkInPool;
- /// <summary> SimType: The current number of Work posted in the thread pool </summary>
- public Int32 GetCurWorkInPool { get { return m_iCurWorkInPool; } set { m_iCurWorkInPool = value; } }
- /// <summary> SimType: Increment current number of Work posted in the thread pool </summary>
- private Int32 IncCurWorkInPool() { return Interlocked.Increment(ref m_iCurWorkInPool); }
- /// <summary> SimType: Decrement current number of Work posted in the thread pool </summary>
- private Int32 DecCurWorkInPool() { return Interlocked.Decrement(ref m_iCurWorkInPool); }
- // Constructor, Finalize, and Dispose
- //***********************************************
- /// <summary> Constructor </summary>
- /// <param name = "iMaxConcurrency"> SimType: Max number of running threads allowed </param>
- /// <param name = "iMinThreadsInPool"> SimType: Min number of threads in the pool </param>
- /// <param name = "iMaxThreadsInPool"> SimType: Max number of threads in the pool </param>
- /// <param name = "pfnUserFunction"> DelType: Reference to a function to call to perform work </param>
- /// <exception cref = "Exception"> Unhandled Exception </exception>
- public IOCPThreadPool(Int32 iMaxConcurrency, Int32 iMinThreadsInPool, Int32 iMaxThreadsInPool, USER_FUNCTION pfnUserFunction)
- {
- try
- {
- // Set initial class state
- GetMaxConcurrency = iMaxConcurrency;//系统允许的最大线程数,如果为0,则和内核数一致,一般都是0,
- GetMinThreadsInPool = iMinThreadsInPool;//最小线程数目
- GetMaxThreadsInPool = iMaxThreadsInPool;//最大线程数目,都是设定给的参数
- GetUserFunction = pfnUserFunction;//传递过来的回调函数,或者说事件处理函数
- // Init the thread counters
- GetCurThreadsInPool = 0;//当前线程池里的线程数
- GetActThreadsInPool = 0;//活动的线程数,正在工作的线程数
- GetCurWorkInPool = 0;//被投递的事件数目
- // Initialize the Monitor Object
- GetCriticalSection = new Object();//来包含类状态的对象????
- // Set the disposing flag to false
- IsDisposed = false;//是否资源释放标志
- unsafe//c#调用外面dll的时候,需要用这个unsafe
- {
- // Create an IO Completion Port for Thread Pool use
- //步骤1:创建iocp端口,
- /*
- * 参数说明编辑
- FileHandle是有效的文件句柄或INVALID_HANDLE_VALUE。
- ExistingCompletionPort是已经存在的完成端口。如果为NULL,则为新建一个IOCP。
- CompletionKey是传送给处理函数的参数。
- NumberOfConcurrentThreads是有多少个线程在访问这个消息队列。当参数ExistingCompletionPort不为0的时候,系统忽略该参数,当该参数为0表示允许同时相等数目于处理器个数的线程访问该消息队列。
- 返回值编辑
- 返回一个IOCP的句柄。若为NULL则创建失败,不为NULL则创建成功。
- *
- * CreateIoCompletionPort的前三个参数只在把设备同Complete Port相关联时才有用。
- 此时我们只需传递INVALID_HANDLE_VALUE,NULL和0即可。
- 第四个参数告诉端口同时能运行的最多线程数,这里设置为0,表示默认为当前计算机的CPU数目。
- */
- GetHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, null, (UInt32)GetMaxConcurrency);
- }
- // Test to make sure the IO Completion Port was created
- if (GetHandle == 0)
- throw new Exception("Unable To Create IO Completion Port");
- // Allocate and start the Minimum number of threads specified
- Int32 iStartingCount = GetCurThreadsInPool;//当前线程池里的线程数目
- ThreadStart tsThread = new ThreadStart(IOCPFunction); 摘要: 表示在 System.Threading.Thread 上执行的方法。public delegate void ThreadStart();
- /*
- * 2 我们的ThreadFun线程函数执行一些初始化之后,将进入一个循环,该循环会在服务进程终止时才结束。
- 在循环中,调用GetQueuedCompletionStatus,这样就把当前线程的ID放入一个等待线程队列中,I/O CP内核对象就总能知道哪个线程在等待处理完成的I/O请求。
- 如果在IDLE_THREAD_TIMEOUT规定的时间内I/O CP上还没有出现一个Completion Packet,则转入下一次循环。在这里我们设置的IDLE_THREAD_TIMEOUT为1秒。
- 当端口的I/O完成队列中出现一项时,完成端口就唤醒等待线程队列中的这个线程,该线程将得到完成的I/O项中的信息: 传输的字节数、完成键和OVERLAPPED结构的地址。
- 在我们的程序中可以用智能指针或者BSTR或者int来接受这个OVERLAPPED结构的地址的值,从而得到消息;然后在这个线程中处理消息。
- GetQueuedCompletionStatus的第一个参数hCompletionPort指出了要监视哪一个端口,这里我们传送先前从CreateIoCompletionPort返回的端口句柄。
- */
- for (Int32 iThread = 0; iThread < GetMinThreadsInPool; ++iThread)
- {
- // Create a thread and start it
- Thread thThread = new Thread(tsThread);
- thThread.Name = "IOCP " + thThread.GetHashCode();
- thThread.Start();
- // Increment the thread pool count
- IncCurThreadsInPool();//原子操作+1初始为0
- /*
- * long m_dwRefCount..
- InterlockedIncrement(&m_dwRefCount)
- 对m_dwRefCount加1
- 在对m_dwRefCount访问的时候其他线程不能访问这个变量
- InterlockedIncrement实现的是原子性的加减,什么是原子性的加减呢?
- 举例:如果一个变量long value = 0;
- 首先说一下正常情况下的加减操作,value+=1;
- 1.系统从value的空间取出值,并动态生成一个空间存储取出来的值;
- 2.将取出来的值和1做加法,并将和放入value的空间覆盖掉原值,操作结束;
- 如果此时有2个Thread,分别记作AThread,BThread
- 1.AThread将value从存储空间取出,为0;
- 2.BThread将value从存储空间取出,为0;
- 3.AThread将取出来的值和1做加法,并将和放入value的空间覆盖掉原值,加法结束,value = 1;
- 4.BThread将取出来的值和1做加法,并将和放入value的空间覆盖掉原值,加法结束,value = 1;
- 最后value应该是2,InterlockedIncrement保证一个线程访问变量时其他线程不能访问。
- 用于增减变量的并不是常用的Inc/Dec过程,而是用了InterlockedIncrement/InterlockedDecrement这一对过程,它们实现的功能完全一样,都是对变量加一或减一。
- 但它们有一个最大的区别,那就是InterlockedIncrement/InterlockedDecrement是线程安全的。
- 即它们在多线程下能保证执行结果正确,而Inc/Dec不能。
- 或者按操作系统理论中的术语来说,这是一对“原语”操作。
- */
- }
- }
- catch
- {
- throw new Exception("Unhandled Exception");
- }
- }
- //***********************************************
- /// <summary> Finalize called by the GC </summary>
- ~IOCPThreadPool()
- {
- /*
- * 这个类结束,应该也意味着是主线程了,所以只有主线程访问?,既然是主线程,为什么还要加标志位呢????
- */
- if (!IsDisposed)//还没有释放资源,则释放,这个应该也是原子操作对isdisposeD吧
- Dispose();
- }
- //**********************************************
- /// <summary> Called when the object will be shutdown. This
- /// function will wait for all of the work to be completed
- /// inside the queue before completing </summary>
- public void Dispose()
- {
- try
- {
- // Flag that we are disposing this object
- IsDisposed = true;
- // Get the current number of threads in the pool
- Int32 iCurThreadsInPool = GetCurThreadsInPool;//现在生成的线程数,用原子操作实现的
- // Shutdown all thread in the pool
- for (Int32 iThread = 0; iThread < iCurThreadsInPool; ++iThread)
- {
- unsafe
- {
- bool bret = PostQueuedCompletionStatus(GetHandle, 4, (UInt32*)SHUTDOWN_IOCPTHREAD, null);
- /*
- * PostQueuedCompletionStatus函数,向每个工作者线程都发送—个特殊的完成数据包。该函数会指示每个线程都“立即结束并退出”.
- * 下面是PostQueuedCompletionStatus函数的定义:
- [cpp] view plain copy
- BOOL PostQueuedCompletionStatus(
- HANDLE CompletlonPort,
- DW0RD dwNumberOfBytesTrlansferred,
- DWORD dwCompletlonKey,
- LPOVERLAPPED lpoverlapped,
- );
- 其中,CompletionPort参数指定想向其发送一个完成数据包的完成端口对象。而就dwNumberOfBytesTransferred,dwCompletionKey和lpOverlapped
- * 这三个参数来说.每—个都允许我们指定—个值,直接传递给GetQueuedCompletionStatus函数中对应的参数。这样—来。
- * —个工作者线程收到传递过来的三个GetQueuedCompletionStatus函数参数后,便可根据由这三个参数的某一个设置的特殊值,
- * 决定何时应该退出。例如,可用dwCompletionPort参数传递0值,而—个工作者线程会将其解释成中止指令。一旦所有工作者线程都已关闭,
- * 便可使用CloseHandle函数,关闭完成端口。最终安全退出程序。
- PostQueuedCompletionStatus函数提供了一种方式来与线程池中的所有线程进行通信。如,当用户终止服务应用程序时,我们想要所有线程都完全利索地退出。
- * 但是如果各线程还在等待完成端口而又没有已完成的I/O 请求,那么它们将无法被唤醒。
- 通过为线程池中的每个线程都调用一次PostQueuedCompletionStatus,我们可以将它们都唤醒。每个线程会对GetQueuedCompletionStatus的返回值进行检查,
- * 如果发现应用程序正在终止,那么它们就可以进行清理工作并正常地退出。
- */
- }
- }
- // Wait here until all the threads are gone
- while (GetCurThreadsInPool != 0) Thread.Sleep(100);
- unsafe
- {
- // Close the IOCP Handle
- CloseHandle(GetHandle);//便可使用CloseHandle函数,关闭完成端口。最终安全退出程序。
- }
- }
- catch
- {
- }
- }
- // Private Methods
- //*******************************************
- /// <summary> IOCP Worker Function that calls the specified user function </summary>
- private void IOCPFunction()
- {
- UInt32 uiNumberOfBytes;
- Int32 iValue;
- try
- {
- while (true)
- {
- unsafe
- {
- OVERLAPPED* pOv;
- // Wait for an event
- /*
- * BOOL GetQueuedCompletionStatus(
- HANDLE CompletionPort,
- LPDWORD lpNumberOfBytes,
- PULONG_PTR lpCompletionKey,
- LPOVERLAPPED *lpOverlapped,
- DWORD dwMilliseconds);
- 调用参数:
- CompletionPort:指定的IOCP,该值由CreateIoCompletionPort函数创建。
- lpnumberofbytes:一次完成后的I/O操作所传送数据的字节数。
- lpcompletionkey:当文件I/O操作完成后,用于存放与之关联的CK。
- lpoverlapped:为调用IOCP机制所引用的OVERLAPPED结构。
- dwmilliseconds:用于指定调用者等待CP的时间。
- 返回值:
- 调用成功,则返回非零数值,相关数据存于lpNumberOfBytes、lpCompletionKey、lpoverlapped变量中。失败则返回零值。
- */
- GetQueuedCompletionStatus(GetHandle, &uiNumberOfBytes, (UInt32*)&iValue, &pOv, INIFINITE);
- }
- // Decrement the number of events in queue
- DecCurWorkInPool();//原子操作,减少一个io里面的任务数目
- // Was this thread told to shutdown
- if (iValue == SHUTDOWN_IOCPTHREAD)//关闭标志位,post传递一个io完成数据,这里读到,知道该结束了,提前约定
- break;
- // Increment the number of active threads
- IncActThreadsInPool();//这个线程读到任务开始工作,增加活动线程数
- try
- {
- // Call the user function
- GetUserFunction(iValue);
- }
- catch
- {
- }
- // Get a lock
- Monitor.Enter(GetCriticalSection);
- try
- {
- // If we have less than max threads currently in the pool
- //当前已经生成了符合设定最小线程数目的线程,如果当前每到最大线程数,继续创建
- if (GetCurThreadsInPool < GetMaxThreadsInPool)
- {
- // Should we add a new thread to the pool
- //所有线程都已在工作
- if (GetActThreadsInPool == GetCurThreadsInPool)
- {
- if (IsDisposed == false)//没有进行资源释放,标志位的作用在这里
- {
- // Create a thread and start it
- ThreadStart tsThread = new ThreadStart(IOCPFunction);
- Thread thThread = new Thread(tsThread);
- thThread.Name = "IOCP " + thThread.GetHashCode();
- thThread.Start();
- // Increment the thread pool count
- IncCurThreadsInPool();//增加当前的活动总数,子线程还可以继续生成线程????
- }
- }
- }
- }
- catch
- {
- }
- // Relase the lock
- Monitor.Exit(GetCriticalSection);//这个是为了保证,比如当前进程为5都在工作了,最大上限设定10,
- //发现都在工作只增加1个额外空闲线程,如果不用 Monitor 是不是会都发现不够一下增加太多,最后可能当前线程数超过10
- // Increment the number of active threads
- DecActThreadsInPool();//干活结束,减少忙碌状态的线程
- }
- }
- catch
- {
- }
- // Decrement the thread pool count
- DecCurThreadsInPool();//线程退出,减少当前进程数
- }
- // Public Methods
- //******************************************
- /// <summary> IOCP Worker Function that calls the specified user function </summary>
- /// <param name="iValue"> SimType: A value to be passed with the event </param>
- /// <exception cref = "Exception"> Unhandled Exception </exception>
- public void PostEvent(Int32 iValue)
- {
- try
- {
- // Only add work if we are not disposing
- if (IsDisposed == false)
- {
- unsafe
- {
- // Post an event into the IOCP Thread Pool
- PostQueuedCompletionStatus(GetHandle, 4, (UInt32*)iValue, null);
- }
- // Increment the number of item of work
- IncCurWorkInPool();
- // Get a lock
- Monitor.Enter(GetCriticalSection);
- try
- {
- // If we have less than max threads currently in the pool
- if (GetCurThreadsInPool < GetMaxThreadsInPool)
- {
- // Should we add a new thread to the pool
- if (GetActThreadsInPool == GetCurThreadsInPool)
- {
- if (IsDisposed == false)
- {
- // Create a thread and start it
- ThreadStart tsThread = new ThreadStart(IOCPFunction);
- Thread thThread = new Thread(tsThread);
- thThread.Name = "IOCP " + thThread.GetHashCode();
- thThread.Start();
- // Increment the thread pool count
- IncCurThreadsInPool();
- }
- }
- }
- }
- catch
- {
- }
- // Release the lock
- Monitor.Exit(GetCriticalSection);
- }
- }
- catch (Exception e)
- {
- throw e;
- }
- catch
- {
- throw new Exception("Unhandled Exception");
- }
- }
- //*****************************************
- /// <summary> IOCP Worker Function that calls the specified user function </summary>
- /// <exception cref = "Exception"> Unhandled Exception </exception>
- public void PostEvent()
- {
- try
- {
- // Only add work if we are not disposing
- if (IsDisposed == false)
- {
- unsafe
- {
- // Post an event into the IOCP Thread Pool
- PostQueuedCompletionStatus(GetHandle, 0, null, null);
- }
- // Increment the number of item of work
- IncCurWorkInPool();
- // Get a lock
- Monitor.Enter(GetCriticalSection);
- try
- {
- // If we have less than max threads currently in the pool
- if (GetCurThreadsInPool < GetMaxThreadsInPool)
- {
- // Should we add a new thread to the pool
- if (GetActThreadsInPool == GetCurThreadsInPool)
- {
- if (IsDisposed == false)
- {
- // Create a thread and start it
- ThreadStart tsThread = new ThreadStart(IOCPFunction);
- Thread thThread = new Thread(tsThread);
- thThread.Name = "IOCP " + thThread.GetHashCode();
- thThread.Start();
- // Increment the thread pool count
- IncCurThreadsInPool();
- }
- }
- }
- }
- catch
- {
- }
- // Release the lock
- Monitor.Exit(GetCriticalSection);
- }
- }
- catch (Exception e)
- {
- throw e;
- }
- catch
- {
- throw new Exception("Unhandled Exception");
- }
- }
- }
- }