在vb.net中通过串口从主机到从机进行读写,无法停止程序,中断循环,不退出



我已经编写了读取和写入串行端口的代码。我需要它无限循环,我一直无法找到一种方法来放置一个按钮来停止循环,如果有错误,它将停止。

我在网上搜索并尝试了人们的建议,但还没有一个真正适合我。

我也不确定显示数据是否更新得足够频繁。这是我第一次使用图形。

我对这一切还很陌生。

'this code has no provision to stop voluntarily, apart from quitting the program.
Imports System.IO.Ports
Class form1
    '==CONTROL CHARACTERS- as per spec==
    '==start and stop values==
    Dim STX As Byte = &H2
    Dim ETX As Byte = &H3
    '==Read==
    Dim read As String = "R"
    '==Acknowledgment==
    Dim ACK As Byte = &H6
    '==class and address==
    Dim DeviceClass As String = "E"
    Dim DeviceAddress As String = "1"
    '==Host Commane==
    Dim hostCommand As String
    '==STX E 1 R REG1 REG0 ETX==
    '==Command to read==
    Dim readSlave As String
    '==STX E 1 ACK REG1 REG0 D1 D0 ETX==
    '==array of register values==
    Dim REG = New String() {"22", "23", "2F", "30"}
    '==set and open port==NB not using get portname- COM1 to be used as dedicated port as spec==
    Private Sub btnStartReset_Click(sender As Object, e As EventArgs) Handles btnStartReset.Click
        If SerialPort1.IsOpen = False Then
            '==Open and set COM1 as host==
            Try
                '==Set COM1 as portname==
                SerialPort1.PortName = "COM1"
                '==Port settings==
                SerialPort1.BaudRate = 9600
                SerialPort1.Parity = Parity.None
                SerialPort1.StopBits = StopBits.One
                SerialPort1.DataBits = 8
                SerialPort1.ReadTimeout = 100
                '==Open port==
                SerialPort1.Open()
                rtbCom1.Text = "COM1 Ready"
                tmrPoll.Start()
            Catch ex As Exception
                rtbCom1.Text = "open error " & ex.Message
            End Try
        End If
    End Sub
    Private Sub tmrPoll_Tick(sender As Object, e As EventArgs) Handles tmrPoll.Tick
        '==timeout error counter==
        Dim i As Integer = 0
        '==Prevent unnecessary timeout errors/allow time lag for port to open==
        Do While SerialPort1.IsOpen = True
            '==Loop through Register==
            For Each register In REG
                '==STX E 1 R REG1 REG0 ETX==
                hostCommand = (STX & DeviceClass & DeviceAddress & read & register & ETX)
                Try
                    '==Loop Host Commands for Register==
                    SerialPort1.WriteLine(hostCommand)
                Catch ex As Exception
                    rtbCom1.Text = "Write Error: " & ex.Message
                End Try
                Try
                    '==readline to separate data==
                    readSlave = SerialPort1.ReadLine()
                    '==display data in GUI==
                    lst1.Items.Add(readSlave)
                    '==Get Register Value==
                    '==STX E 1 ACK REG1 REG0 D1 D0 ETX==
                    '==2-E-1-6-R-R-D-D-3==
                    '==Get the Data Value for Individual Register==
                    Dim reg = readSlave.Substring(4, 2)
                    '==convert data to integer, so data can be displayed graphically==
                    Dim D1 = CInt(readSlave.Substring(6, 1))
                    Dim D0 = CInt(readSlave.Substring(7, 1))
                    '==Display received substring values==
                    Select Case reg
                        Case Is = "22"
                            'list box until advised.
                            lst1.Items.Add(reg & D1 & D0)
                        Case Is = "23"
                            '==display data as shape==
                            '==0-100==
                            shpTemp.Width = (D1 + D0)
                        Case Is = "2F"
                            '==0-5==
                            shpAmp.Width = (D1 + D0) * 20
                        Case Is = "30"
                            '==0-40==
                            shpVolt.Width = (D1 + D0) * 2.5
                    End Select
                Catch ex As Exception
                    rtbCom1.Text = "Read error: " & ex.Message
                    i += 1
                End Try
                If i > 2 Then
                    rtbCom1.Text = "Operation Aborted: 3 timeout errors."
                    '==Stop program if 3 timeout errors- as spec/closed port==
                    SerialPort1.Close()
                    rtbCom1.Text = "port closed - Operation Aborted: 3 timeout errors."
                    shpAmp.Width = 1
                    shpTemp.Width = 1
                    shpVolt.Width = 1
                    tmrPoll.Stop()
                    Exit Do
                End If
            Next
        Loop
    End Sub
End Class

对于WinForm项目,UI是单线程的。消息循环(处理来自操作系统的传入消息,例如按钮单击)与UI事件处理程序(例如tmrPoll_Tick事件处理程序方法)在同一线程上运行。因此,在一个UI事件的事件处理程序退出之前,消息循环将不会处理下一个OS消息。由于这种情况,如果您在tmrPoll_Tick中处于无限循环中,它将完全锁定UI,因为它将阻止消息循环处理任何更多的消息。

因此,作为规则,在WinForm项目中,你不应该在UI事件处理程序中创建一个无限或长时间运行的循环。你需要重新设计你的代码,让它更受事件驱动(在一个重复发生的事件中一次做一件工作),或者你需要在一个单独的线程中运行循环,这样它就不会阻塞UI线程。如果你想用一个单独的线程来做这件事,一个流行的选择是使用BackgroundWorker组件,你可以在你的表单设计器工具箱中找到它。

相关内容

最新更新