-4

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

我已经搜索了互联网并尝试了人们的建议,但还没有找到真正适合我的建议。

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

我对这一切还是陌生的。

'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
4

1 回答 1

4

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

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

于 2013-05-11T13:36:18.073 回答