AccessViolationException reading from USB

本文关键字:USB from reading AccessViolationException | 更新日期: 2023-09-27 17:58:52

我有以下代码,不明白为什么我会定期收到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);

此外,以下是来自Exception的堆栈跟踪:

   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()

AccessViolationException reading from USB

陈的博客http://blogs.msdn.com/b/oldnewthing/archive/2011/02/02/10123392.aspx

很有可能在调用CancelIO之后I/O还没有完成,并且您违反了博客中所述的基本规则。也就是说,"OVERLAPPED结构必须保持有效,直到I/O完成"。

尝试在调用FreeHGlobal之前添加WaitForSingleObject(eventObject, 0xFFFFFFFF)(或INFINITE使用的任何常量)。

此外,您可以简化switch语句如下:

            case WAIT_TIMEOUT:
            default:
                CancelIo(readHandle);
                break;