4

在 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 设备、endpointwriter 上尝试了许多不同的 Dispose 和 Exit 变体,但到目前为止没有成功。我假设在断开连接之前某些东西保持打开状态,所以我收到此错误,但我不确定它是什么以及如何摆脱它。

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

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

4

2 回答 2

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;
    }
}

希望能帮助到你。

于 2014-10-09T04:20:58.197 回答
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();
        }
    }
}

希望此片段可以帮助其他在尝试解决问题时发现此问题的人。

于 2014-09-19T09:57:53.733 回答