Best solution for interop with a driver

T

Thomas

Hi

I do have a question for the .NET experts. :)
Im running WindowsCE 5.0 with CF 2.0. My application reads data from a
device driver when a events is received from the driver.
I could use the interop (DllImport) and then use the native functions
WaitForSingleObject and ReadFile to read the data.
But would I get better speed performance using a COM object handling the
device driver communication?
What about wrapping the device driver functions in a managed C++ class. Then
the C# application can get data from that?
Are there no noticable speed diffrences between the suggestions?


/Thomas
 
P

Paul G. Tobey [eMVP]

There's no way that I can think of that making something a COM object would
improve performance. What mechanism are you thinking of?

Managed C++ is unsupported on devices so, even if it had something to do
with performance in this case, which it doesn't, it can't really be used.

The operations that you need to do, WaitForSingleObject() and ReadFile() are
the same in all of these cases. There's no difference between calling
WaitForSingleObject from managed C++ or C# or C or anything else. At most,
there might be some minor overhead in managed code for loading the DLL that
contains WaitForSingleObject and getting its address. I suppose that you
might see that if you're calling WaitForSingleObject every five ms or
something, but by the nature of what you're doing, most of the time is going
to be in the wait, not in calling the Wait function.

Paul T.
 
T

Thomas

Ok, I see.

If I use ReadFile to my driver, then the function call sometimes returns
with the status that the read was OK. But the returned read byte is zero. The
buffer allso is empty...
Running the same code as C++ (Rewritten to C++), then the ReadFile returns
every time with valid data. (So I assume that the driver work fine?)

Why does the ReadFile sometimes fail when used in C#??

I first thought that the buffer used by the ReadFile, somehow got
reallocated by the carbage collector.
But moving the ReadFile to unsafe section and using a fixed byte array as
ouput buffer, still makes the ReadFile return with no reads.

When using GetLastError (Marshal.GetLastWin32Error()), the error in system
is ERROR_ACCESS_DENIED (0x80000005)

Why does this only happen in C# and not in C++?

My readfile declaration:
[DllImport("coredll.dll", EntryPoint="ReadFile", SetLastError = true)]
public static extern unsafe int CEReadFile(IntPtr hFile, void* lpBuffer, int
nNumberOfBytesToRead, int* lpNumberOfBytesRead, int lpOverlapped);

Unsafe function using the readfile:

public unsafe int Read(byte[] buffer)
{
int n = 0;
fixed (byte* p = new byte[16])
{
int iReadError = MPC.HAL.StreamInterface.CEReadFile(CANFile, p, 16,
&n, 0);
if (iReadError == 0)
return -1;
if (n == 0)
// Sometime happens, but the readfile status is ok!!!!
System.Diagnostics.Debug.WriteLine("Zero read");
}
// Read bytes
return n;
}
 
P

Paul G. Tobey [eMVP]

I wouldn't say that it is failing. Zero is a valid return, depending on how
you've set the port receive time-outs (if the read times out and no bytes
have been received, there's nothing it can reasonably return but zero). Zero
is not an error indication, so getting the last error after Read returns zero
bytes isn't going to give you a valid error code; there was no error.

Paul T.

Thomas said:
Ok, I see.

If I use ReadFile to my driver, then the function call sometimes returns
with the status that the read was OK. But the returned read byte is zero. The
buffer allso is empty...
Running the same code as C++ (Rewritten to C++), then the ReadFile returns
every time with valid data. (So I assume that the driver work fine?)

Why does the ReadFile sometimes fail when used in C#??

I first thought that the buffer used by the ReadFile, somehow got
reallocated by the carbage collector.
But moving the ReadFile to unsafe section and using a fixed byte array as
ouput buffer, still makes the ReadFile return with no reads.

When using GetLastError (Marshal.GetLastWin32Error()), the error in system
is ERROR_ACCESS_DENIED (0x80000005)

Why does this only happen in C# and not in C++?

My readfile declaration:
[DllImport("coredll.dll", EntryPoint="ReadFile", SetLastError = true)]
public static extern unsafe int CEReadFile(IntPtr hFile, void* lpBuffer, int
nNumberOfBytesToRead, int* lpNumberOfBytesRead, int lpOverlapped);

Unsafe function using the readfile:

public unsafe int Read(byte[] buffer)
{
int n = 0;
fixed (byte* p = new byte[16])
{
int iReadError = MPC.HAL.StreamInterface.CEReadFile(CANFile, p, 16,
&n, 0);
if (iReadError == 0)
return -1;
if (n == 0)
// Sometime happens, but the readfile status is ok!!!!
System.Diagnostics.Debug.WriteLine("Zero read");
}
// Read bytes
return n;
}





Paul G. Tobey said:
There's no way that I can think of that making something a COM object would
improve performance. What mechanism are you thinking of?

Managed C++ is unsupported on devices so, even if it had something to do
with performance in this case, which it doesn't, it can't really be used.

The operations that you need to do, WaitForSingleObject() and ReadFile() are
the same in all of these cases. There's no difference between calling
WaitForSingleObject from managed C++ or C# or C or anything else. At most,
there might be some minor overhead in managed code for loading the DLL that
contains WaitForSingleObject and getting its address. I suppose that you
might see that if you're calling WaitForSingleObject every five ms or
something, but by the nature of what you're doing, most of the time is going
to be in the wait, not in calling the Wait function.

Paul T.
 
T

Thomas

Hi Paul

In normal cases, reading zero bytes isnt an error. I agree.
But the device driver, where Im calling readfile on, is written by me. Does
the read generate an error in the driver, the ReadFile does return an error.
Data are allways returned, so a succesful read schouldnt contain zero bytes.
Allso, running the same test setup, but with the ReadFile called directly
from C++ code, then the readfile never return zero data.
Allso using the platform builder debugger (allthough its hard to debug at
the same time), the driver do return data. But when the ReadFile return in
the C# application, zero bytes has been read.

So I cant see why the C# ReadFile sometime return zero data, but the C++
equilant does never?

But maybe that a thing I just have to handle in the application then. :)

/Thomas

Paul G. Tobey said:
I wouldn't say that it is failing. Zero is a valid return, depending on how
you've set the port receive time-outs (if the read times out and no bytes
have been received, there's nothing it can reasonably return but zero). Zero
is not an error indication, so getting the last error after Read returns zero
bytes isn't going to give you a valid error code; there was no error.

Paul T.

Thomas said:
Ok, I see.

If I use ReadFile to my driver, then the function call sometimes returns
with the status that the read was OK. But the returned read byte is zero. The
buffer allso is empty...
Running the same code as C++ (Rewritten to C++), then the ReadFile returns
every time with valid data. (So I assume that the driver work fine?)

Why does the ReadFile sometimes fail when used in C#??

I first thought that the buffer used by the ReadFile, somehow got
reallocated by the carbage collector.
But moving the ReadFile to unsafe section and using a fixed byte array as
ouput buffer, still makes the ReadFile return with no reads.

When using GetLastError (Marshal.GetLastWin32Error()), the error in system
is ERROR_ACCESS_DENIED (0x80000005)

Why does this only happen in C# and not in C++?

My readfile declaration:
[DllImport("coredll.dll", EntryPoint="ReadFile", SetLastError = true)]
public static extern unsafe int CEReadFile(IntPtr hFile, void* lpBuffer, int
nNumberOfBytesToRead, int* lpNumberOfBytesRead, int lpOverlapped);

Unsafe function using the readfile:

public unsafe int Read(byte[] buffer)
{
int n = 0;
fixed (byte* p = new byte[16])
{
int iReadError = MPC.HAL.StreamInterface.CEReadFile(CANFile, p, 16,
&n, 0);
if (iReadError == 0)
return -1;
if (n == 0)
// Sometime happens, but the readfile status is ok!!!!
System.Diagnostics.Debug.WriteLine("Zero read");
}
// Read bytes
return n;
}





Paul G. Tobey said:
There's no way that I can think of that making something a COM object would
improve performance. What mechanism are you thinking of?

Managed C++ is unsupported on devices so, even if it had something to do
with performance in this case, which it doesn't, it can't really be used.

The operations that you need to do, WaitForSingleObject() and ReadFile() are
the same in all of these cases. There's no difference between calling
WaitForSingleObject from managed C++ or C# or C or anything else. At most,
there might be some minor overhead in managed code for loading the DLL that
contains WaitForSingleObject and getting its address. I suppose that you
might see that if you're calling WaitForSingleObject every five ms or
something, but by the nature of what you're doing, most of the time is going
to be in the wait, not in calling the Wait function.

Paul T.

:

Hi

I do have a question for the .NET experts. :)
Im running WindowsCE 5.0 with CF 2.0. My application reads data from a
device driver when a events is received from the driver.
I could use the interop (DllImport) and then use the native functions
WaitForSingleObject and ReadFile to read the data.
But would I get better speed performance using a COM object handling the
device driver communication?
What about wrapping the device driver functions in a managed C++ class. Then
the C# application can get data from that?
Are there no noticable speed diffrences between the suggestions?


/Thomas
 
P

Paul G. Tobey [eMVP]

Without having your driver, I can't fully accept the notion that the most
likely source of the problem is the framework. I'd still point to your
driver, then. It's making a bunch of assumptions about how the drivers are
going to work. If yours doesn't, who knows...

Paul T.

Thomas said:
Hi Paul

In normal cases, reading zero bytes isnt an error. I agree.
But the device driver, where Im calling readfile on, is written by me.
Does
the read generate an error in the driver, the ReadFile does return an
error.
Data are allways returned, so a succesful read schouldnt contain zero
bytes.
Allso, running the same test setup, but with the ReadFile called directly
from C++ code, then the readfile never return zero data.
Allso using the platform builder debugger (allthough its hard to debug at
the same time), the driver do return data. But when the ReadFile return in
the C# application, zero bytes has been read.

So I cant see why the C# ReadFile sometime return zero data, but the C++
equilant does never?

But maybe that a thing I just have to handle in the application then. :)

/Thomas

Paul G. Tobey said:
I wouldn't say that it is failing. Zero is a valid return, depending on
how
you've set the port receive time-outs (if the read times out and no bytes
have been received, there's nothing it can reasonably return but zero).
Zero
is not an error indication, so getting the last error after Read returns
zero
bytes isn't going to give you a valid error code; there was no error.

Paul T.

Thomas said:
Ok, I see.

If I use ReadFile to my driver, then the function call sometimes
returns
with the status that the read was OK. But the returned read byte is
zero. The
buffer allso is empty...
Running the same code as C++ (Rewritten to C++), then the ReadFile
returns
every time with valid data. (So I assume that the driver work fine?)

Why does the ReadFile sometimes fail when used in C#??

I first thought that the buffer used by the ReadFile, somehow got
reallocated by the carbage collector.
But moving the ReadFile to unsafe section and using a fixed byte array
as
ouput buffer, still makes the ReadFile return with no reads.

When using GetLastError (Marshal.GetLastWin32Error()), the error in
system
is ERROR_ACCESS_DENIED (0x80000005)

Why does this only happen in C# and not in C++?

My readfile declaration:
[DllImport("coredll.dll", EntryPoint="ReadFile", SetLastError = true)]
public static extern unsafe int CEReadFile(IntPtr hFile, void*
lpBuffer, int
nNumberOfBytesToRead, int* lpNumberOfBytesRead, int lpOverlapped);

Unsafe function using the readfile:

public unsafe int Read(byte[] buffer)
{
int n = 0;
fixed (byte* p = new byte[16])
{
int iReadError = MPC.HAL.StreamInterface.CEReadFile(CANFile, p,
16,
&n, 0);
if (iReadError == 0)
return -1;
if (n == 0)
// Sometime happens, but the readfile status is ok!!!!
System.Diagnostics.Debug.WriteLine("Zero read");
}
// Read bytes
return n;
}





:

There's no way that I can think of that making something a COM object
would
improve performance. What mechanism are you thinking of?

Managed C++ is unsupported on devices so, even if it had something to
do
with performance in this case, which it doesn't, it can't really be
used.

The operations that you need to do, WaitForSingleObject() and
ReadFile() are
the same in all of these cases. There's no difference between
calling
WaitForSingleObject from managed C++ or C# or C or anything else. At
most,
there might be some minor overhead in managed code for loading the
DLL that
contains WaitForSingleObject and getting its address. I suppose that
you
might see that if you're calling WaitForSingleObject every five ms or
something, but by the nature of what you're doing, most of the time
is going
to be in the wait, not in calling the Wait function.

Paul T.

:

Hi

I do have a question for the .NET experts. :)
Im running WindowsCE 5.0 with CF 2.0. My application reads data
from a
device driver when a events is received from the driver.
I could use the interop (DllImport) and then use the native
functions
WaitForSingleObject and ReadFile to read the data.
But would I get better speed performance using a COM object
handling the
device driver communication?
What about wrapping the device driver functions in a managed C++
class. Then
the C# application can get data from that?
Are there no noticable speed diffrences between the suggestions?


/Thomas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top