D
dvestal
I'm trying to use Overlapped I/O from C#, and utterly failing. I've
tried to boil down my code to as simple an example as possible, in
hopes that you people can point to where I'm going wrong. I've
included my test program. The behavior I'm seeing is that the callback
routine is never called, despite the fact that the thread is (AFAIK) in
an alertable state. The program just hangs waiting for the
m_doneEvent.
In other scenarios, I'm able to transfer data, but it is sometimes
received as zeros instead of the real data. Any help, or pointers to a
good discussion of managed overlapped I/O using pipes, would be
appreciated. I'd love a website, but I can buy a book if need be.
static unsafe class Program
{
static private AutoResetEvent m_doneEvent = new AutoResetEvent(false);
static private string m_action = string.Empty;
[DllImport("kernel32.dll", EntryPoint = "ReadFileEx", SetLastError =
true,
CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern int ReadFileEx(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int nNumberOfBytesToRead,
NativeOverlapped* lpOverlapped,
[MarshalAs(UnmanagedType.FunctionPtr)] IOCompletionCallback callback
);
[DllImport("kernel32.dll", EntryPoint = "WriteFileEx", SetLastError =
true,
CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern int WriteFileEx(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int nNumberOfBytesToWrite,
NativeOverlapped* lpOverlapped,
[MarshalAs(UnmanagedType.FunctionPtr)] IOCompletionCallback callback
);
[STAThread]
static void Main()
{
ManualResetEvent actionCompletedEvent = new ManualResetEvent(false);
Overlapped overlapped = new Overlapped(0, 0,
actionCompletedEvent.SafeWaitHandle.DangerousGetHandle(),
null);
IOCompletionCallback callback = Finished;
byte[] bytes = new byte[1000];
NativeOverlapped* nativeOverlapped = overlapped.Pack(callback,
bytes);
IntPtr m_pipeHandle = CreateNamedPipe(
@"\\.\pipe\DSV",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
PIPE_UNLIMITED_INSTANCES,
2048,
2048,
1000,
null
);
for(int i = 0; i < 100; i++)
{
System.Diagnostics.Trace.WriteLine("Beginning transfer");
new Random().NextBytes(bytes);
m_action = "Writing";
WriteFileEx(m_pipeHandle,
bytes,
bytes.Length,
nativeOverlapped,
callback);
m_doneEvent.WaitOne();
m_action = "Reading";
ReadFileEx(m_pipeHandle,
bytes,
1000,
nativeOverlapped,
callback);
m_doneEvent.WaitOne();
}
System.Diagnostics.Trace.WriteLine("all done");
}
[ComVisibleAttribute(true)]
static public void Finished(
uint errorCode,
uint bytesTransferred,
NativeOverlapped* overlapped)
{
System.Diagnostics.Trace.WriteLine(
m_action
+ ": errorCode=" + errorCode
+ " bytesTransferred=" + bytesTransferred);
m_doneEvent.Set();
}
}
tried to boil down my code to as simple an example as possible, in
hopes that you people can point to where I'm going wrong. I've
included my test program. The behavior I'm seeing is that the callback
routine is never called, despite the fact that the thread is (AFAIK) in
an alertable state. The program just hangs waiting for the
m_doneEvent.
In other scenarios, I'm able to transfer data, but it is sometimes
received as zeros instead of the real data. Any help, or pointers to a
good discussion of managed overlapped I/O using pipes, would be
appreciated. I'd love a website, but I can buy a book if need be.
static unsafe class Program
{
static private AutoResetEvent m_doneEvent = new AutoResetEvent(false);
static private string m_action = string.Empty;
[DllImport("kernel32.dll", EntryPoint = "ReadFileEx", SetLastError =
true,
CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern int ReadFileEx(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int nNumberOfBytesToRead,
NativeOverlapped* lpOverlapped,
[MarshalAs(UnmanagedType.FunctionPtr)] IOCompletionCallback callback
);
[DllImport("kernel32.dll", EntryPoint = "WriteFileEx", SetLastError =
true,
CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern int WriteFileEx(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int nNumberOfBytesToWrite,
NativeOverlapped* lpOverlapped,
[MarshalAs(UnmanagedType.FunctionPtr)] IOCompletionCallback callback
);
[STAThread]
static void Main()
{
ManualResetEvent actionCompletedEvent = new ManualResetEvent(false);
Overlapped overlapped = new Overlapped(0, 0,
actionCompletedEvent.SafeWaitHandle.DangerousGetHandle(),
null);
IOCompletionCallback callback = Finished;
byte[] bytes = new byte[1000];
NativeOverlapped* nativeOverlapped = overlapped.Pack(callback,
bytes);
IntPtr m_pipeHandle = CreateNamedPipe(
@"\\.\pipe\DSV",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
PIPE_UNLIMITED_INSTANCES,
2048,
2048,
1000,
null
);
for(int i = 0; i < 100; i++)
{
System.Diagnostics.Trace.WriteLine("Beginning transfer");
new Random().NextBytes(bytes);
m_action = "Writing";
WriteFileEx(m_pipeHandle,
bytes,
bytes.Length,
nativeOverlapped,
callback);
m_doneEvent.WaitOne();
m_action = "Reading";
ReadFileEx(m_pipeHandle,
bytes,
1000,
nativeOverlapped,
callback);
m_doneEvent.WaitOne();
}
System.Diagnostics.Trace.WriteLine("all done");
}
[ComVisibleAttribute(true)]
static public void Finished(
uint errorCode,
uint bytesTransferred,
NativeOverlapped* overlapped)
{
System.Diagnostics.Trace.WriteLine(
m_action
+ ": errorCode=" + errorCode
+ " bytesTransferred=" + bytesTransferred);
m_doneEvent.Set();
}
}