蓝宇网络 www.py668.com

非淡泊无以明志,非宁静无以致远。

导航

C# IOCP

VC++中我几乎每一个Windows Service都是采用I/O完成端口。至于在C#中如何使用I/O完成端口,一直很少见人提及。 William Kennedy的三篇文章《IOCP Thread Pooling in C#》,对实现这种机制很有帮助,唯一美中不足的是,它只能把int数值压入完成端口,而无法像VC++中那样可以将接口指针/BSTR字符串等等转为OVERLAPPED*。我试了很多遍Marshal.PtrToStructure/StructureToPtr 和StringToBSTR,总是无法成功通过I/O完成端口传递string。

我还曾经用以下这2个函数将string转换为byte[],然后将byte[]转换为NativeOverlapped。总是不行。

System.Threading.NativeOverlapped Ov = new NativeOverlapped();
byte[] btRaw = Str2Arr(strValue);
Ov = (System.Threading.NativeOverlapped)
RawDeserialize(btRaw, typeof(System.Threading.NativeOverlapped));

函数声明如下:
public static byte[] Str2Arr(String s)
{
return (new UnicodeEncoding()).GetBytes(s);
}
public static string Arr2Str(byte[] buffer)
{
return (new UnicodeEncoding()).GetString(buffer, 0, buffer.Length);
}
public static byte[] RawSerialize( object anything )
{
int rawsize = Marshal.SizeOf( anything );
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.StructureToPtr( anything, buffer, false );
byte[] rawdatas = new byte[ rawsize ];
Marshal.Copy( buffer, rawdatas, 0, rawsize );
Marshal.FreeHGlobal( buffer );
return rawdatas;
}

public static object RawDeserialize( byte[] rawdatas, Type anytype )
{
int rawsize = Marshal.SizeOf( anytype );
if( rawsize > rawdatas.Length )
return null;
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.Copy( rawdatas, 0, buffer, rawsize );
object retobj = Marshal.PtrToStructure( buffer, anytype );
Marshal.FreeHGlobal( buffer );
return retobj;
}


开始我也一样迷惑怎样传送对象引用,后来经过研究发现可以这样解决完成端口传送对象的问题。使用以下方式来声明api:

[DllImport("Kernel32")]
private static extern bool PostQueuedCompletionStatus(UInt32 completionPort, int numberOfBytesTransferred,IntPtr completionKey, IntPtr overlapped);
[DllImport("Kernel32")]
private static extern bool GetQueuedCompletionStatus(UInt32 completionPort, ref int numberOfBytes,ref IntPtr completionKey, ref IntPtr overlapped,UInt32 milliseconds);

使用GetQueuedCompletionStatus和PostQueuedCompletionStatus的时候,用GCHandle对象来取得对象的指针,再传送给它们作为参数就可以了。

int i=0;
object Value=new object();
GCHandle gcValue=GCHandle.Alloc(Value);
GCHandle gcKey=GCHandle.Alloc(i);
// Post an event into the IOCP Thread Pool
PostQueuedCompletionStatus(GetHandle, 4, (IntPtr)gcKey, (IntPtr)gcValue);

其它的按这个思路去解决就可以了。

文章来自:http://www.cnblogs.com/zhengyun_ustc/archive/2005/04/11/135827.html

posted on 2006-09-09 20:16  罗记  阅读(1713)  评论(1编辑  收藏  举报