【问题标题】:Vb.net - Cross-threading exception by closing a formVb.net - 通过关闭表单的跨线程异常
【发布时间】:2012-10-11 13:31:06
【问题描述】:

我正在开发一个从串行端口(COMM 端口)读取内容的应用程序。 简而言之,它的工作原理是这样的:当您在酒吧或餐厅工作时,您必须先扫描一张卡片,然后才能在收银机中输入内容。如果这张卡返回一个好的数字,你可以输入一些东西。

因此,必须有一个表单来监听串口并检查是否有人扫描卡以及是否是具有良好权限的卡。

如果此人具有良好的权限,则可以关闭表单并调用另一个表单。

现在,在代码中:

这里,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 并且无法在此处关闭它...... 但我不知道如何解决这个问题。

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

【问题讨论】:

    标签: vb.net multithreading formclosing


    【解决方案1】:

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

    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 线程调用给定方法。

    【讨论】:

    • 有效!我之前试过这个,但是我把这几行代码放在了frmMenu中。非常感谢!
    猜你喜欢
    • 2014-05-23
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多