我有以下代码,不明白为什么我会定期获取AccessViolationException或COMException。任何帮助将非常感激。谢谢。
IntPtr eventObject = IntPtr.Zero;
NativeOverlapped HidOverlapped = new NativeOverlapped();
Byte[] inputReportBuffer = null;
Int32 numberOfBytesRead = 0;
Int32 result = 0;
Boolean success = false;
IntPtr unManagedBuffer = IntPtr.Zero;
IntPtr unManagedOverlapped = IntPtr.Zero;
Array.Resize(ref inputReportBuffer, Capabilities.InputReportByteLength);
eventObject = CreateEvent
(IntPtr.Zero,
false,
false,
String.Empty);
HidOverlapped.OffsetLow = 0;
HidOverlapped.OffsetHigh = 0;
HidOverlapped.EventHandle = eventObject;
unManagedBuffer = Marshal.AllocHGlobal(inputReportBuffer.Length);
unManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(HidOverlapped));
Marshal.StructureToPtr(HidOverlapped, unManagedOverlapped, false);
success = ReadFile
(readHandle,
unManagedBuffer,
inputReportBuffer.Length,
ref numberOfBytesRead,
unManagedOverlapped);
while (!busyWait()) ;
// If ReadFile returned true, report is available. Otherwise, check for completion
if (!success)
{
result = WaitForSingleObject(eventObject, 1000);
switch (result)
{
case WAIT_OBJECT_0:
success = true;
GetOverlappedResult
(readHandle,
unManagedOverlapped,
ref numberOfBytesRead,
false);
break;
case WAIT_TIMEOUT:
CancelIo(readHandle);
break;
default:
CancelIo(readHandle);
break;
}
}
if (success)
{
// Report was received.
// Copy Received data to inputReportBuffer for application use
Marshal.Copy(unManagedBuffer, inputReportBuffer, 0, numberOfBytesRead);
ProcessUSB(inputReportBuffer);
}
Marshal.FreeHGlobal(unManagedOverlapped); // <-- AccessViolationException Here.
Marshal.FreeHGlobal(unManagedBuffer);
success = HidD_FreePreparsedData(preparsedData);
此外,这是来自例外的堆栈跟踪:
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Runtime.InteropServices.Marshal.FreeHGlobal(IntPtr hglobal)
at TWEEQ.MainWindow.ReadUSB()
at TWEEQ.MainWindow.myTimer_Elapsed(Object sender, ElapsedEventArgs e)
at System.Timers.Timer.MyTimerCallback(Object state)
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback()
答案 0 :(得分:2)
Per Raymond Chen的博客http://blogs.msdn.com/b/oldnewthing/archive/2011/02/02/10123392.aspx
在调用CancelIO
并且您违反博客中规定的基本规则后,I / O很可能无法完成。即,&#34; OVERLAPPED结构必须保持有效,直到I / O完成&#34;。
在致电WaitForSingleObject(eventObject, 0xFFFFFFFF)
之前,请尝试添加FreeHGlobal
(或用于INFINITE的任何常量)。
此外,您可以按如下方式简化switch
声明:
case WAIT_TIMEOUT:
default:
CancelIo(readHandle);
break;