Search code examples
c#multithreadingpinvokereadfile

Multithreaded ReadFile calls using pinvoke gives STATUS_INVALID_USER_BUFFER


I'm writing some code to read blocks from a binary file bypassing the buffering in FileStream as it causes problem when using LockFileEx to lock regions of the file. This code is pretty much identical to the implementation in FileStream from reference source.

private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, out int hr)
{
    int r = 0;
    int numBytesRead = 0;
    fixed (byte* p = bytes)
    {
        r = Native.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero);
    }

where ReadFile is imported thusly:

unsafe internal static extern int ReadFile(SafeFileHandle handle, byte* bytes, 
                              int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);

My code has 8 threads each trying to read from the file, each with a separate file handle with its own read pointer, and I'm reading from a 35GB file in 80K chunks. Occasionally this read fails with an error 0xc00000e8 (STATUS_INVALID_USER_BUFFER) but I don't understand why.

What could be causing this problem, and how can I resolve it?


Solution

  • I managed to resolve the problem using GCHandle.Alloc

                GCHandle gch = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                try
                {
                    r = WdfWin32Native.ReadFile(handle, bytes, count, out numBytesRead, IntPtr.Zero);
                }
                finally
                {
                    gch.Free();
                }
    

    with ReadFile declared:

    unsafe internal static extern int ReadFile(SafeFileHandle handle,
                  byte [] bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);
    

    I'm not sure why this fixes the issue, but it does seem to.