Vb.net - 关闭表单的跨线程异常

时间:2012-10-11 13:31:06

标签: vb.net multithreading formclosing

我正在开发一个从串口(COMM-port)读取内容的应用程序。 简而言之,它的工作方式如下:当您在酒吧或餐厅工作时,在您可以在注册表中输入内容之前,您必须扫描一种卡片。如果此卡返回一个好的号码,您可以输入一些内容。

因此,必须有一个表格可以监听串口并检查是否有人扫描了一张卡,以及是否是一张拥有良好权利的卡。

如果该人拥有良好的权利,则可以关闭该表格并调用另一种表格。

现在,在代码中:

这里加载了MenuForm(读取正确代码后必须可访问的表单)。我叫frmWaiterKey出现。

Private Sub frmMenu_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim oForm As frmWaiterKey = New frmWaiterKey()
    oForm.ShowDialog()
End Sub

类frmWaiterKey的代码:

Private Sub frmWaiterKey_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    nameArray = SerialPort.GetPortNames
    OpenComPort()
    AddHandler myComPort.DataReceived, SerialDataReceivedEventHandler1
End Sub

Sub OpenComPort()

    Try
        ' Get the selected COM port's name 
        ' from the combo box.
        If Not myComPort.IsOpen Then
            myComPort.PortName = _
            nameArray(0).ToString()
            ' Get the selected bit rate from the combo box.
            myComPort.BaudRate = CInt(9600)
            ' Set other port parameters.
            myComPort.Parity = Parity.None
            myComPort.DataBits = 8
            myComPort.StopBits = StopBits.One
            myComPort.Handshake = Handshake.None

            'myComPort.ReadTimeout = 3000
            'myComPort.WriteTimeout = 5000

            ' Open the port.
            myComPort.Open()

        End If

    Catch ex As InvalidOperationException
        MessageBox.Show(ex.Message)
    Catch ex As UnauthorizedAccessException
        MessageBox.Show(ex.Message)
    Catch ex As System.IO.IOException
        MessageBox.Show(ex.Message)
    End Try

End Sub
Sub CloseComPort()

    Using myComPort
        If (Not (myComPort Is Nothing)) Then
            ' The COM port exists.
            If myComPort.IsOpen Then
                ' Wait for the transmit buffer to empty.
                Do While (myComPort.BytesToWrite > 0)
                Loop
            End If
        End If
    End Using

End Sub

Private SerialDataReceivedEventHandler1 As New SerialDataReceivedEventHandler(AddressOf DataReceived)

' Specify the routine that runs when 
' a DataReceived event occurs at myComPort.

' This routine runs when data arrives at myComPort.

Friend Sub DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
    Dim newReceivedData As String
    ' Get data from the COM port.
    newReceivedData = myComPort.ReadExisting
    newReceivedData = newReceivedData.Trim()
    MsgBox(newReceivedData)
    If newReceivedData.Equals("00150324294764") Then
        CloseComPort()
        Me.Close()
    End If

End Sub

我在最后一行收到错误:Me.Close() 我明白了这一点:我从frmMenu调用frmWaiterKey表单,不能在这里关闭它... 但我不知道如何解决这个问题。

我希望有人能帮助我或告诉我我做错了什么。

1 个答案:

答案 0 :(得分:5)

首先,你需要制作一个这样的方法:

Private Sub CloseMe()
    If Me.InvokeRequired Then
        Me.Invoke(New MethodInvoker(AddressOf CloseMe))
        Exit Sub
    End If
    Me.Close()
End Sub

然后,通过调用该方法关闭您的表单,如下所示:

If newReceivedData.Equals("00150324294764") Then
    CloseComPort()
    CloseMe()
End If

这是必要的原因是因为WinForms中的所有UI活动必须从同一个线程执行。由于从另一个线程调用DataReceived方法,因此它必须在关闭表单之前返回到UI线程。如果你在UI线程以外的任何线程上,InvokeRequired属性返回true,Invoke方法从UI线程调用给定的方法。