从USB读取AccessViolationException

时间:2014-04-18 16:04:03

标签: c# wpf access-violation

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

1 个答案:

答案 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;