[C#]I/O完成端口的类定义和测试实例

<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>

从William Kennedy那里整理过来的,不同之处在于他自己定义了一个Overlapped,而我们这里直接使用
System.Threading.NativeOverlapped.

附一段我以前的Win32下的IOCP文档,如果您了解IOCP也可以直接跳过看后面的C#测试示范:

整理者:郑昀@UltraPower

我们采用的是I/O Complete Port(以下简称IOCP)处理机制。

简单的讲,当服务应用程序初始化时,它应该先创建一个I/O CP。我们在请求到来后,将得到的数据打包用PostQueuedCompletionStatus发送到IOCP中。这时需要创建一些个线程(7个线程/CPU,再多就没有意义了)来处理发送到IOCP端口的消息。实现步骤大致如下:

1 先在主线程中调用CreateIoCompletionPort创建IOCP

CreateIoCompletionPort的前三个参数只在把设备同Complete Port相关联时才有用。

此时我们只需传递INVALID_HANDLE_VALUE,NULL0即可。

第四个参数告诉端口同时能运行的最多线程数,这里设置为0,表示默认为当前计算机的CPU数目。

2 我们的ThreadFun线程函数执行一些初始化之后,将进入一个循环,该循环会在服务进程终止时才结束。

在循环中,调用GetQueuedCompletionStatus,这样就把当前线程的ID放入一个等待线程队列中,I/O CP内核对象就总能知道哪个线程在等待处理完成的I/O请求。

如果在IDLE_THREAD_TIMEOUT规定的时间内I/O CP上还没有出现一个Completion Packet,则转入下一次循环。在这里我们设置的IDLE_THREAD_TIMEOUT1秒。

当端口的I/O完成队列中出现一项时,完成端口就唤醒等待线程队列中的这个线程,该线程将得到完成的I/O项中的信息: 传输的字节数、完成键和OVERLAPPED结构的地址。

在我们的程序中可以用智能指针或者BSTR或者int来接受这个OVERLAPPED结构的地址的值,从而得到消息;然后在这个线程中处理消息。

GetQueuedCompletionStatus的第一个参数hCompletionPort指出了要监视哪一个端口,这里我们传送先前从CreateIoCompletionPort返回的端口句柄。

需要注意的是:

第一, 线程池的数目是有限制的,和CPU数目有关系。

第二, IOCP是一种较为完美的睡眠/唤醒 线程机制;线程当前没有任务要处理时,就进入睡眠状态,从而不占用CPU资源,直到被内核唤醒;

第三, 最近一次刚执行完的线程,下次任务来的时候还会唤醒它;所以有可能比较少被调用的线程以后被调用的几率也少。


测试代码:


using System;
using System.Threading; // IncludedfortheThread.Sleepcall
using Continuum.Threading;
using System.Runtime.InteropServices;

namespace IOCPDemo
{
//=============================================================================
/**////<summary></summary>Sampleclassforthethreadingclass
publicclassUtilThreadingSample
{
//*****************************************************************************
/**////<summary></summary>TestMethod
staticvoidMain()
{
//CreatetheMSSQLIOCPThreadPool
IOCPThreadPoolpThreadPool=newIOCPThreadPool(0,10,20,newIOCPThreadPool.USER_FUNCTION(IOCPThreadFunction));

//for(inti=1;i
{
pThreadPool.PostEvent(
1234);
}


Thread.Sleep(
100);

pThreadPool.Dispose();
}


//********************************************************************
/**////<summary></summary>FunctiontobecalledbytheIOCPthreadpool.Calledwhen
///acommandispostedforprocessingbytheSocketManager
///Thevalueprovidedbythethreadpostingtheevent

staticpublicvoidIOCPThreadFunction(intiValue)
{
try
{
Console.WriteLine(
"Value:{0}",iValue.ToString());
Thread.Sleep(
3000);
}


catch(ExceptionpException)
{
Console.WriteLine(pException.Message);
}

}

}


}



类代码:
using System;
using System.Threading;
using System.Runtime.InteropServices;

namespace IOCPThreading
{
[StructLayout(LayoutKind.Sequential,CharSet
=CharSet.Auto)]

publicsealedclassIOCPThreadPool
{
[DllImport(
"Kernel32",CharSet=CharSet.Auto)]
privateunsafestaticexternUInt32CreateIoCompletionPort(UInt32hFile,UInt32hExistingCompletionPort,UInt32*puiCompletionKey,UInt32uiNumberOfConcurrentThreads);

[DllImport(
"Kernel32",CharSet=CharSet.Auto)]
privateunsafestaticexternBooleanCloseHandle(UInt32hObject);

[DllImport(
"Kernel32",CharSet=CharSet.Auto)]
privateunsafestaticexternBooleanPostQueuedCompletionStatus(UInt32hCompletionPort,UInt32uiSizeOfArgument,UInt32*puiUserArg,System.Threading.NativeOverlapped*pOverlapped);

[DllImport(
"Kernel32",CharSet=CharSet.Auto)]
privateunsafestaticexternBooleanGetQueuedCompletionStatus(UInt32hCompletionPort,UInt32*pSizeOfArgument,UInt32*puiUserArg,System.Threading.NativeOverlapped**ppOverlapped,UInt32uiMilliseconds);

privateconstUInt32INVALID_HANDLE_VALUE=0xffffffff;
privateconstUInt32INIFINITE=0xffffffff;
privateconstInt32SHUTDOWN_IOCPTHREAD=0x7fffffff;
publicdelegatevoidUSER_FUNCTION(intiValue);
privateUInt32m_hHandle;
privateUInt32GetHandle{get{returnm_hHandle;}set{m_hHandle=value;}}

privateInt32m_uiMaxConcurrency;

privateInt32GetMaxConcurrency{get{returnm_uiMaxConcurrency;}set{m_uiMaxConcurrency=value;}}


privateInt32m_iMinThreadsInPool;

privateInt32GetMinThreadsInPool{get{returnm_iMinThreadsInPool;}set{m_iMinThreadsInPool=value;}}

privateInt32m_iMaxThreadsInPool;

privateInt32GetMaxThreadsInPool{get{returnm_iMaxThreadsInPool;}set{m_iMaxThreadsInPool=value;}}


privateObjectm_pCriticalSection;

privateObjectGetCriticalSection{get{returnm_pCriticalSection;}set{m_pCriticalSection=value;}}


privateUSER_FUNCTIONm_pfnUserFunction;

privateUSER_FUNCTIONGetUserFunction{get{returnm_pfnUserFunction;}set{m_pfnUserFunction=value;}}


privateBooleanm_bDisposeFlag;

/**////<summary></summary>SimType:Flagtoindicateiftheclassisdisposing

privateBooleanIsDisposed{get{returnm_bDisposeFlag;}set{m_bDisposeFlag=value;}}

privateInt32m_iCurThreadsInPool;

/**////<summary></summary>SimType:Thecurrentnumberofthreadsinthethreadpool

publicInt32GetCurThreadsInPool{get{returnm_iCurThreadsInPool;}set{m_iCurThreadsInPool=value;}}

/**////<summary></summary>SimType:Incrementcurrentnumberofthreadsinthethreadpool

privateInt32IncCurThreadsInPool(){returnInterlocked.Increment(refm_iCurThreadsInPool);}

/**////<summary></summary>SimType:Decrementcurrentnumberofthreadsinthethreadpool

privateInt32DecCurThreadsInPool(){returnInterlocked.Decrement(refm_iCurThreadsInPool);}


privateInt32m_iActThreadsInPool;

/**////<summary></summary>SimType:Thecurrentnumberofactivethreadsinthethreadpool

publicInt32GetActThreadsInPool{get{returnm_iActThreadsInPool;}set{m_iActThreadsInPool=value;}}

/**////<summary></summary>SimType:Incrementcurrentnumberofactivethreadsinthethreadpool

privateInt32IncActThreadsInPool(){returnInterlocked.Increment(refm_iActThreadsInPool);}

/**////<summary></summary>SimType:Decrementcurrentnumberofactivethreadsinthethreadpool

privateInt32DecActThreadsInPool(){returnInterlocked.Decrement(refm_iActThreadsInPool);}


privateInt32m_iCurWorkInPool;

/**////<summary></summary>SimType:ThecurrentnumberofWorkpostedinthethreadpool

publicInt32GetCurWorkInPool{get{returnm_iCurWorkInPool;}set{m_iCurWorkInPool=value;}}

/**////<summary></summary>SimType:IncrementcurrentnumberofWorkpostedinthethreadpool

privateInt32IncCurWorkInPool(){returnInterlocked.Increment(refm_iCurWorkInPool);}

/**////<summary></summary>SimType:DecrementcurrentnumberofWorkpostedinthethreadpool

privateInt32DecCurWorkInPool(){returnInterlocked.Decrement(refm_iCurWorkInPool);}

publicIOCPThreadPool(Int32iMaxConcurrency,Int32iMinThreadsInPool,Int32iMaxThreadsInPool,USER_FUNCTIONpfnUserFunction)
{
try
{
//Setinitialclassstate

GetMaxConcurrency
=iMaxConcurrency;

GetMinThreadsInPool
=iMinThreadsInPool;

GetMaxThreadsInPool
=iMaxThreadsInPool;

GetUserFunction
=pfnUserFunction;


//Initthethreadcounters

GetCurThreadsInPool
=0;

GetActThreadsInPool
=0;

GetCurWorkInPool
=0;


//InitializetheMonitorObject

GetCriticalSection
=newObject();


//Setthedisposingflagtofalse

IsDisposed
=false;


unsafe
{

//CreateanIOCompletionPortforThreadPooluse
GetHandle=CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,null,(UInt32)GetMaxConcurrency);

}



//TesttomakesuretheIOCompletionPortwascreated

if(GetHandle==0)

thrownewException("UnableToCreateIOCompletionPort");


//AllocateandstarttheMinimumnumberofthreadsspecified

Int32iStartingCount
=GetCurThreadsInPool;



ThreadStarttsThread
=newThreadStart(IOCPFunction);

for(Int32iThread=0;iThreadGetMinThreadsInPool;++iThread)
{

//Createathreadandstartit

ThreadthThread
=newThread(tsThread);

thThread.Name
="IOCP"+thThread.GetHashCode();

thThread.Start();


//Incrementthethreadpoolcount

IncCurThreadsInPool();

}


}



catch
{

thrownewException("UnhandledException");

}


}


~IOCPThreadPool()
{

if(!IsDisposed)

Dispose();

}


publicvoidDispose()
{

try
{

//Flagthatwearedisposingthisobject

IsDisposed
=true;


//Getthecurrentnumberofthreadsinthepool

Int32iCurThreadsInPool
=GetCurThreadsInPool;


//Shutdownallthreadinthepool

for(Int32iThread=0;iThreadiCurThreadsInPool;++iThread)
{
unsafe
{

boolbret=PostQueuedCompletionStatus(GetHandle,4,(UInt32*)SHUTDOWN_IOCPTHREAD,null);

}


}



//Waithereuntilallthethreadsaregone

while(GetCurThreadsInPool!=0)Thread.Sleep(100);


unsafe
{

//ClosetheIOCPHandle
CloseHandle(GetHandle);

}


}


catch
{

}


}

privatevoidIOCPFunction()
{
UInt32uiNumberOfBytes;

Int32iValue;

try
{
while(true)
{

unsafe
{

System.Threading.NativeOverlapped
*pOv;


//Waitforanevent

GetQueuedCompletionStatus(GetHandle,
&uiNumberOfBytes,(UInt32*)&iValue,&pOv,INIFINITE);
}


//Decrementthenumberofeventsinqueue

DecCurWorkInPool();


//Wasthisthreadtoldtoshutdown

if(iValue==SHUTDOWN_IOCPTHREAD)

break;


//Incrementthenumberofactivethreads

IncActThreadsInPool();


try
{
//Calltheuserfunction
GetUserFunction(iValue);

}


catch(Exceptionex)
{
throwex;
}



//Getalock

Monitor.Enter(GetCriticalSection);


try
{

//Ifwehavelessthanmaxthreadscurrentlyinthepool

if(GetCurThreadsInPoolGetMaxThreadsInPool)
{

//Shouldweaddanewthreadtothepool

if(GetActThreadsInPool==GetCurThreadsInPool)
{

if(IsDisposed==false)
{

//Createathreadandstartit

ThreadStarttsThread
=newThreadStart(IOCPFunction);

ThreadthThread
=newThread(tsThread);

thThread.Name
="IOCP"+thThread.GetHashCode();

thThread.Start();


//Incrementthethreadpoolcount

IncCurThreadsInPool();

}


}


}


}


catch
{

}



//Relasethelock

Monitor.Exit(GetCriticalSection);


//Incrementthenumberofactivethreads

DecActThreadsInPool();

}


}



catch(Exceptionex)
{
stringstr=ex.Message;

}



//Decrementthethreadpoolcount

DecCurThreadsInPool();

}


//publicvoidPostEvent(Int32iValue
publicvoidPostEvent(intiValue)
{

try
{

//Onlyaddworkifwearenotdisposing

if(IsDisposed==false)
{

unsafe
{

//PostaneventintotheIOCPThreadPool

PostQueuedCompletionStatus(GetHandle,
4,(UInt32*)iValue,null);

}



//Incrementthenumberofitemofwork

IncCurWorkInPool();


//Getalock

Monitor.Enter(GetCriticalSection);


try
{

//Ifwehavelessthanmaxthreadscurrentlyinthepool

if(GetCurThreadsInPoolGetMaxThreadsInPool)
{

//Shouldweaddanewthreadtothepool

if(GetActThreadsInPool==GetCurThreadsInPool)
{

if(IsDisposed==false)
{

//Createathreadandstartit

ThreadStarttsThread
=newThreadStart(IOCPFunction);

ThreadthThread
=newThread(tsThread);

thThread.Name
="IOCP"+thThread.GetHashCode();

thThread.Start();


//Incrementthethreadpoolcount

IncCurThreadsInPool();

}


}


}


}



catch
{

}



//Releasethelock

Monitor.Exit(GetCriticalSection);

}


}



catch(Exceptione)
{

throwe;

}



catch
{

thrownewException("UnhandledException");

}


}


publicvoidPostEvent()
{

try
{

//Onlyaddworkifwearenotdisposing

if(IsDisposed==false)
{

unsafe
{

//PostaneventintotheIOCPThreadPool

PostQueuedCompletionStatus(GetHandle,
0,null,null);

}



//Incrementthenumberofitemofwork

IncCurWorkInPool();


//Getalock

Monitor.Enter(GetCriticalSection);


try

{

//Ifwehavelessthanmaxthreadscurrentlyinthepool

if(GetCurThreadsInPoolGetMaxThreadsInPool)

{

//Shouldweaddanewthreadtothepool

if(GetActThreadsInPool==GetCurThreadsInPool)

{

if(IsDisposed==false)

{

//Createathreadandstartit

ThreadStarttsThread
=newThreadStart(IOCPFunction);

ThreadthThread
=newThread(tsThread);

thThread.Name
="IOCP"+thThread.GetHashCode();

thThread.Start();


//Incrementthethreadpoolcount

IncCurThreadsInPool();

}


}


}


}



catch

{

}



//Releasethelock

Monitor.Exit(GetCriticalSection);

}


}


catch

{

thrownewException("UnhandledException");

}


}


}


}




你可能感兴趣的:(I/O)