SerialPort close方法抛出未捕获的异常

时间:2013-12-29 03:10:34

标签: vb.net serial-port ioexception

我正在使用SerialPort对象通过USB与外部设备进行通信。我遇到一个问题,其中Close()方法似乎抛出一个System.IO.IOException,它没有被周围的catch块捕获并导致程序锁定。

这是我收到的调试信息:

The thread '<No Name>' (0x1c0c) has exited with code 0 (0x0).
A first chance exception of type 'System.IO.IOException' occurred in System.dll
A first chance exception of type 'System.IO.IOException' occurred in System.dll

这是代码的具体摘录:

Try
    _connOpen = False
    RemoveHandler serialPort.DataReceived, AddressOf serialPort_DataReceived
    serialPort.RtsEnable = False
    serialPort.DtrEnable = False
    Application.DoEvents()


    serialPort.DiscardInBuffer()    ' clear input buffer

    serialPort.Close()    ' close the port 

    MyBase.OnConnectionChanged(EventArgs.Empty)

Catch ex As IOException
    Debug.Print("Exception caught")
    serialPort.Dispose()
    serialPort = Nothing
End Try

尽管调试告诉我抛出了IOException,但从未输入Catch块。我使用断点跟踪此行的异常。

3 个答案:

答案 0 :(得分:2)

  

似乎抛出了一个System.IO.IOException,它没有被周围的catch块

捕获

正在处理 ,您只看到“第一次机会”通知,而不是“异常未处理”消息。这些异常发生在工作线程上,SerialPort开始生成DataReceived,ErrorReceived和PinChanged事件。

你得到这个是因为你在接收数据时关闭了端口,设置DtrEnable = False只能在你给串行设备时间看信号变化时才能工作,你不要等待足够长的时间。 DoEvents()是危险的,并没有修复它,因为它只延迟了〜微秒,你需要一秒钟才能确定。激活USB连接器然后尝试关闭端口是另一种触发异常的好方法,很少有USB设备驱动程序能够顺利处理这种情况。

  

并导致程序锁定

这是你真正的问题。当您在接收数据时关闭端口并在DataReceived事件处理程序中出错时,SerialPort.Close()将死锁。在事件处理程序停止运行之前,端口无法关闭。标准错误是在事件处理程序中使用Control.Invoke(),通常使用,因为您无法从工作线程更新UI。但这是一种非常危险的方法,很容易造成死锁。在UI线程空闲之前,它无法完成。它不是空闲的,它停留在Close呼叫中。在事件处理程序停止运行之前无法完成。它不会停止运行,它会停留在Invoke()调用中。死锁城市。

始终使用Control.BeginInvoke()代替,它不会导致死锁。在另一个线程上调用Close()也是一个创可贴。

答案 1 :(得分:1)

当您拨打serialPort.Close()时,您实际上正在呼叫serialPort.Dispose()。来自反射器:

Public Sub Close()
    MyBase.Dispose
End Sub

要捕获异常,您需要将serialPort.Dispose()放在catch块中;

Try
    '...
    serialPort.Close()
    '...
Catch ex As IOException
    Debug.Print("Exception caught")
End Try

或者您可以通过查看Open状态来执行此操作:

Try
    '...
    serialPort.Close()
    '...
Catch ex As IOException
    Debug.Print("Exception caught")
    If ((Not serialPort Is Nothing) AndAlso serialPort.IsOpen) Then
        serialPort.Close()
        serialPort = Nothing
    End If
End Try

答案 2 :(得分:0)

我解决方案我发现其他似乎工作的地方是有一个标志来关闭端口

closePort = True

然后在收到的数据上检查标志并关闭端口:

Private Sub serialPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles serialPort.DataReceived
    If closePort Then
        serialPort.Close()
    Else
        readSerialPortData()
    End If
End Sub