LibUsbDotNet:退出WPF应用程序时出错 - 安全句柄已关闭

时间:2013-12-30 14:03:46

标签: c# wpf usb libusb libusbdotnet

在WPF应用程序中使用USB设备,我可以成功连接并向设备发送命令。设备只接收命令,没有回复,所以我只需要一个EndpointWriter与它进行通信。

MyUsbFinder = new UsbDeviceFinder(vid, pid);
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
    wholeUsbDevice.SetConfiguration(1);
    wholeUsbDevice.ClaimInterface(0);
}

writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);

然后写入设备的过程:

byte[] update = { some bytes };
int bytesWritten;

if (MyUsbDevice != null)
{
     ec = writer.Write(update, 2000, out bytesWritten);
}

一切正常,包括关闭应用程序,除非在工作过程中USB设备断开然后重新连接。应用程序成功处理此方案并重新连接到设备,继续成功向其发送命令:

public bool reconnect()
{
    //clear the info so far
    if (MyUsbDevice != null)
    {
        writer.Dispose();
        wholeUsbDevice.ReleaseInterface(0);
        wholeUsbDevice.Close();
        MyUsbDevice.Close();
        UsbDevice.Exit();
    }

    //now start over
    MyUsbFinder = new UsbDeviceFinder(vid, pid);
    MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);

...    等等。

在发生此类断开/重新连接后关闭应用程序时出现问题。尽管该程序成功运行并与设备通信了很长时间,但在退出时我得到以下异常:

System.ObjectDisposedException was unhandled
  Message="Safe handle has been closed"
  Source="mscorlib"
  ObjectName=""
  StackTrace:
       at System.StubHelpers.StubHelpers.SafeHandleC2NHelper(Object pThis, IntPtr pCleanupWorkList)
       at LibUsbDotNet.Internal.Kernel32.GetOverlappedResult(SafeHandle hDevice, IntPtr lpOverlapped, Int32& lpNumberOfBytesTransferred, Boolean bWait)
       at LibUsbDotNet.Internal.LibUsb.LibUsbAPI.GetOverlappedResult(SafeHandle interfaceHandle, IntPtr pOverlapped, Int32& numberOfBytesTransferred, Boolean wait)
       at LibUsbDotNet.Internal.OverlappedTransferContext.Wait(Int32& transferredCount, Boolean cancel)
       at LibUsbDotNet.Main.UsbTransfer.Wait(Int32& transferredCount)
       at LibUsbDotNet.Main.UsbTransfer.Dispose()
       at LibUsbDotNet.Main.UsbTransfer.Finalize()
  InnerException: 

我在usb设备上尝试了许多不同的Dispose和Exit变体,即终点编写器,但到目前为止还没有成功。我假设在断开连接之前一些东西仍然打开,所以我得到了这个错误,但我不确定它是什么以及如何摆脱它。

因为只有在关闭应用程序时才会发生这种情况,我不介意甚至能够以某种方式忽略异常并让应用程序死掉但是我不确定如何在Window_Closing事件成功返回时捕获该异常然后异常发生在那之后所以我无法抓住它......

任何提示都表示赞赏,谢谢!

2 个答案:

答案 0 :(得分:5)

我在Windows服务中收到了类似的异常。我的调用堆栈如下:

Exception Info: System.ObjectDisposedException
Stack:
   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean ByRef)
   at System.StubHelpers.StubHelpers.SafeHandleAddRef(System.Runtime.InteropServices.SafeHandle, Boolean ByRef)
   at LibUsbDotNet.Internal.Kernel32.GetOverlappedResult(System.Runtime.InteropServices.SafeHandle, IntPtr, Int32 ByRef, Boolean)
   at LibUsbDotNet.Internal.LibUsb.LibUsbAPI.GetOverlappedResult(System.Runtime.InteropServices.SafeHandle, IntPtr, Int32 ByRef, Boolean)
   at LibUsbDotNet.Internal.OverlappedTransferContext.Wait(Int32 ByRef, Boolean)
   at LibUsbDotNet.Main.UsbTransfer.Dispose()
   at LibUsbDotNet.Main.UsbTransfer.Finalize()

要解决此问题,我通过添加LibUsbDotNet.Internal.LibUsb.LibUsbAPI.GetOverlappedResult()的检查来修复interfaceHandle.IsClosed方法。现在该方法如下:

public override bool GetOverlappedResult(SafeHandle interfaceHandle, IntPtr pOverlapped, out int numberOfBytesTransferred, bool wait)
{
    // To prevent ObjectDisposedException check if SafeHandle's been closed
    if (!interfaceHandle.IsClosed)
        return Kernel32.GetOverlappedResult(interfaceHandle, pOverlapped, out numberOfBytesTransferred, wait);
    else
    {
        numberOfBytesTransferred = 0;
        return true;
    }
}

希望它有所帮助。

答案 1 :(得分:3)

我一直有类似的问题"安全句柄已关闭"在关闭我的WPF应用程序时发生ObjectDisposedException。

我的堆栈跟踪略有不同:

System.ObjectDisposedException was unhandled  
  HResult=-2146232798  
  Message=Safe handle has been closed  
  Source=mscorlib  
  ObjectName=""  
  StackTrace:  
       at System.Threading.WaitHandle.WaitOneNative(SafeHandle waitableSafeHandle, UInt32 millisecondsTimeout, Boolean hasThreadAffinity, Boolean exitContext)  
       at System.Threading.WaitHandle.InternalWaitOne(SafeHandle waitableSafeHandle, Int64 millisecondsTimeout, Boolean hasThreadAffinity, Boolean exitContext)  
       at System.Threading.WaitHandle.WaitOne(Int32 millisecondsTimeout, Boolean exitContext)  
       at LibUsbDotNet.Main.UsbTransfer.get_IsCancelled()  
       at LibUsbDotNet.Main.UsbTransfer.Dispose()  
       at LibUsbDotNet.Main.UsbTransfer.Finalize()  
  InnerException:

但是,我设法通过将以下代码添加到我的发送和接收函数来修复它。

using (UsbEndpointWriter writer = device.OpenEndpointWriter(WriteEndpoint))
{
    UsbTransfer usbTransfer = null;

    try
    {
        // Code to do transfer here .. not shown as not pertinent here..
    }
    finally
    {
        if (usbTransfer != null)
        {
            // **** Start of code added to fix ObjectDisposedException
            if (!usbTransfer.IsCancelled || !usbTransfer.IsCompleted)
            {
                usbTransfer.Cancel();
            }
            // **** End of code added to fix ObjectDisposedException
            usbTransfer.Dispose();
        }
    }
}

希望这段代码可以帮助其他人在尝试修复问题时找到这个问题。