在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;
}