IOCP是一种高性能的I/O模型,更多资料可以google下。
在.Net Framework下,没有提供IOCP的类库,我们需要引入Win32 API来建立IOCP Thread Pool。
我们用CreateIOCompletionPort获得一个IOCP对象的句柄,用PostQueuedCompetionStatus把状态对象(Socket编程下一般系传socket)放进队列,开启一定量线程来运行GetQueuedCompletionStatus监听,GetQueuedCompletionStatus函数会阻塞调用线程。
由于与非托管代码打交道,要实现Safe的代码,有几点需要注意。
1.我们要传递一个状态对象地址给非托管代码,由于GC的关系,我们不能直接传递地址,因为GC在回收的过程中,会移动在堆上的对象,造成地址改变。一般来说,GC移动会修改托管代码里面地址指向,但我们现在把地址传递出托管代码范围,GC也无能为力了。情况如图。
针对这种情况,可以用GCHandle类解决,GCHandle类的Alloc方法为对象注册,Alloc方法有两个参数,第二个参数系GCHandleType类型枚举,默认情况系Normal。当我们要GC不移动对象的时候,例如有个byte[]的Buffer需要非托管代码填充,可以使用Pinned。
GCHandle gch = GCHandle.Alloc(obj);
PostQueuedCompletionStatus(GetHandle, (uint)Marshal.SizeOf(gch), IntPtr.Zero, (IntPtr)gch);
2.PostQueuedCompletionStatus函数的第二个参数是要传送数据的长度,直接使用sizeof系unsafe代码,这里使用Marshal.SizeOf方法。
3.还有需要注意的是,传递的对象必须实现[StructLayout(LayoutKind.Sequential)]标签,以保证该对象的成员在内存里连续分配,遵守C++方式。
4.利用SafeFileHandle引用内核对象更安全,这个类能实现引用计数。
至此,已经讲述完实现Safe代码的要点了。
IOCPThreadPool的实现代码:
测试代码:
参考资料:
IOCP Thread Pooling in C# - Part I
http://www.devarticles.com/c/a/C-Sharp/IOCP-Thread-Pooling-in-C-sharp-Part-I/
IOCP Thread Pooling in C# - Part II
http://www.devarticles.com/c/a/C-Sharp/IOCP-Thread-Pooling-in-C-sharp-Part-II/
蛙蛙推荐:在c#使用IOCP(完成端口)的简单示例
http://www.cnblogs.com/onlytiancai/archive/2009/01/05/1241571.html