ネイティブのC#の代替手段は遅いため、kernel32のReadFileを機能させようとしています...
次のコードは数回機能していましたが、突然「保護されたメモリの読み取りまたは書き込みを試みました。これは、多くの場合、他のメモリが破損していることを示しています。」
サーバーを再起動すると、同じエラーが発生する前に数回機能すると思いましたが、間違っていたようです。今何をしても発生します..
これが私のコードです:
using System.Runtime.InteropServices;
private WinFileIO.WinFileIO _winFile;
_winFile = new WinFileIO.WinFileIO(new byte[bufferSize]);
_winFile.OpenForReading(_fileInfo.FullName);
public WinFileIO(Array Buffer)
{
PinBuffer(Buffer);
pHandleRead = IntPtr.Zero;
pHandleWrite = IntPtr.Zero;
bufferSize = Buffer.GetLength(0);
}
private void PinBuffer(Array Buffer)
{
UnpinBuffer();
gchBuf = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
IntPtr pAddr = Marshal.UnsafeAddrOfPinnedArrayElement(Buffer, 0);
// pBuffer is the pointer used for all of the I/O functions in this class.
pBuffer = (void*)pAddr.ToPointer();
}
public void UnpinBuffer()
{
if (gchBuf.IsAllocated)
gchBuf.Free();
}
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe System.IntPtr CreateFile
(
string FileName, // file name
uint DesiredAccess, // access mode
uint ShareMode, // share mode
uint SecurityAttributes, // Security Attributes
uint CreationDisposition, // how to create
uint FlagsAndAttributes, // file attributes
int hTemplateFile // handle to template file
);
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
private unsafe static extern bool ReadFile
(
int hFile,
byte[] arraypBuffer,
int NumberOfBytesToRead,
ref int lpNumberOfBytesToRead,
int* ptr
);
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe bool SetFilePointer
(
System.IntPtr hObject,
int lDistanceToMove,
ref int lpDistanceToMoveHigh,
EMoveMethod dwMoveMethod
);
public void OpenForReading(string FileName)
{
Close(true, false);
pHandleRead = CreateFile(FileName, 3, 3, 0, OPEN_EXISTING, 0, 0);
if (pHandleRead == System.IntPtr.Zero)
{
Win32Exception WE = new Win32Exception();
ApplicationException AE = new ApplicationException("WinFileIO:OpenForReading - Could not open file " +
FileName + " - " + WE.Message);
throw AE;
}
}
public void MoveOffset(int moveDistance, EMoveMethod moveMethod)
{
if (pHandleRead != System.IntPtr.Zero)
{
int moveDistanceHigh = 0;
SetFilePointer(pHandleRead, moveDistance, ref moveDistanceHigh, moveMethod);
}
}
public unsafe Tuple<int, byte[]> ReadChunk(int bufferSize, int offset)
{
int bytesRead = 0;
byte[] bufBytes = new byte[bufferSize];
MoveOffset(offset, EMoveMethod.Begin);
int pointer = (int)Marshal.PtrToStructure(pHandleRead, typeof(int));
if (ReadFile(pointer, bufBytes, bufferSize, ref bytesRead, null))
{
byte[] outBytes = new byte[bytesRead];
Array.Copy(bufBytes, outBytes, bytesRead);
return new Tuple<int, byte[]>(bytesRead, outBytes);
}
return null;
}
関連するコードはこれだけだと思います。
CreateFile および ReadFile 署名が完全に互換性がない (IntPtr と int)、IntPtr の Marshal.PtrToStructure が本来あるべき場所を指していない、またはメモリが解放されていないなどと関係があると思います。ただし、再起動後に数回試行しても機能しなかったという事実は、私を混乱させます。
誰でも明らかなことを見つけたり、私が調査できる提案はありますか?
ありがとう
編集:お気づきかもしれませんが、これはさまざまなアプローチの寄せ集めのようなものです。バッファの内容を必要なように読み取るのに苦労したため、ピン留めされたバッファはもう使用していません。
Edit2:スタックトレースは、これが問題であると言います:
at System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr ptr, Type structureType)