Timer1冻结UI线程

时间:2017-08-31 09:51:12

标签: vb.net multithreading asynchronous timer backgroundworker

我的程序从serialport获取高速数据,并且计时器读取它,在计时器获得值之后,计时器被禁用并且代码执行sting操作,其中添加之前从com接受到listview的值。问题是UI线程并没有完全冻结,但是当我拖动表单时看起来很迟钝,那个每次在subitem.text上添加+1的代码都不顺利。

   founditem.SubItems(4).Text = founditem.SubItems(4).Text + 1

为什么知道计时器创建自己的线程,它不应该冻结UI(我不能摆脱计时器,因为它需要从串口接受正确的数据) 有小费吗?我试过invoke,begininvoke和background_worker,也许不正确。 我也可以从计时器事件中调用后台工作者吗?我不擅长asyc任务。我的代码是:

   Private Sub spOpen()
    Try
        spClose()
        spObj.PortName = "COM4"
        spObj.BaudRate = 230400
        spObj.Parity = IO.Ports.Parity.None
        spObj.DataBits = 8
        spObj.StopBits = IO.Ports.StopBits.One
        spObj.Handshake = IO.Ports.Handshake.None
        spObj.DtrEnable = False 'imp
        spObj.RtsEnable = False 'imp
        spObj.NewLine = vbCr
        spObj.ReadTimeout = 0
        spObj.WriteTimeout = 250
        spObj.ReceivedBytesThreshold = 1
        spObj.Open()

    Catch ex As Exception
        'catch 
    End Try
End Sub
Private Sub spClose()
    Try
        If spObj.IsOpen Then
            spObj.Close()
            spObj.Dispose()
        End If
    Catch ex As Exception
        'handle the way you want
    End Try
End Sub
Function ReverseString(ByVal sText As String) As String
    Dim lenText As Long, lPos As Long
    If Len(sText) = 0 Then Exit Function
    lenText = Len(sText)
    ReverseString = Space(lenText)

    For lPos = lenText To 1 Step -2
        If lPos > 0 Then Mid(ReverseString, lenText - lPos + 1, 2) = Mid(sText, lPos - 1, 2)
        If lPos = 0 Then Mid(ReverseString, lenText - lPos + 1, 2) = Mid(sText, lPos, 2)
    Next lPos
    'Return


End Function

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    'stop the timer (stops this function being called while it is still working
    Timer1.Enabled = False


    ' get any new data and add the the global variable receivedData
    receivedData = ReceiveSerialData()

    'If receivedData contains a "<" and a ">" then we have data
    If ((receivedData.Contains("<") And receivedData.Contains(">"))) Then
        'parseData()
        first_msg = 1

        parseData()
    End If

    ' restart the timer
    Timer1.Enabled = True
End Sub
Function  ReceiveSerialData() As String
    Dim Incoming As String
    Try
        Incoming = spObj.ReadExisting()
        If Incoming Is Nothing Then
            Return "nothing" & vbCrLf
        Else
            Return Incoming
        End If
    Catch ex As TimeoutException
        Return "Error: Serial Port read timed out."
    End Try
End Function
Function parseData()

    ' uses the global variable receivedData
    Dim pos1 As Integer
    Dim pos2 As Integer
    Dim length As Integer
    Dim newCommand As String
    Dim done As Boolean = False
    Dim count As Integer = 0

    While (Not done)

        pos1 = receivedData.IndexOf("<") + 1
        pos2 = receivedData.IndexOf(">") + 1

        'occasionally we may not get complete data and the end marker will be in front of the start marker
        ' for exampe "55><T0056><"
        ' if pos2 < pos1 then remove the first part of the string from receivedData
        If (pos2 < pos1) Then
            receivedData = Microsoft.VisualBasic.Mid(receivedData, pos2 + 1)
            pos1 = receivedData.IndexOf("<") + 1
            pos2 = receivedData.IndexOf(">") + 1
        End If

        If (pos1 = 0 Or pos2 = 0) Then
            ' we do not have both start and end markers and we are done
            done = True

        Else
            ' we have both start and end markers

            length = pos2 - pos1 + 1
            If (length > 0) Then
                'remove the start and end markers from the command
                newCommand = Mid(receivedData, pos1 + 1, length - 2)

                ' show the command in the text box
                RichTextBox1.Text = ""
                RichTextBox1.AppendText(newCommand & vbCrLf)

                'remove the command from receivedData
                receivedData = Mid(receivedData, pos2 + 1)
                'RichTextBox1.Text &= receivedData


                uart_in = RichTextBox1.Text
                data = ""
                'RichTextBox2.Text = Mid(RichTextBox1.Text, 6, 3)
                'If RichTextBox1.TextLength = 26 Then

                can_id = Mid(uart_in, 6, 3) 'extracting and id
                dlc = Mid(uart_in, 10, 1)
                data = uart_in.Substring(26 - (dlc * 2))
                hex2ascii(data)
                data = data.InsertEveryNthChar(" ", 2)
                '  data = ReverseString(data)
                Dim articlecheck As String = can_id
                Dim founditem As ListViewItem = ListView1.FindItemWithText(articlecheck)
                If Not (founditem Is Nothing) Then
                    founditem.SubItems(0).Text = can_id
                    founditem.SubItems(1).Text = dlc
                    '  If founditem.SubItems(2).Text <> data Then
                    ' founditem.SubItems(2).ForeColor = Color.LightYellow
                    founditem.SubItems(2).Text = data
                    '  End If

                    founditem.SubItems(3).Text = timer_count - founditem.SubItems(3).Text
                    founditem.SubItems(4).Text = founditem.SubItems(4).Text + 1
                    founditem.SubItems(5).Text = asciival
                    ' timer_count = 1
                    first_msg = 0
                Else
                    Dim lvi As New ListViewItem(can_id)
                    lvi.SubItems.Add(dlc)
                    lvi.SubItems.Add(data)
                    lvi.SubItems.Add(timer_count)
                    lvi.SubItems.Add(count)
                    lvi.SubItems.Add(asciival)
                    ListView1.Items.Add(lvi)

                End If

            End If ' (length > 0) 

        End If '(pos1 = 0 Or pos2 = 0)

    End While

End Function
Function hex2ascii(ByVal hextext As String) As String
    Dim a As Integer
    Dim y As Integer
    Dim value As String
    Dim num As String


    For y = 1 To Len(hextext) Step 2
        num = Mid(hextext, y, 2)
        a = Val("&h" & num)
        If a = 160 Or a = 0 Or a = 9 Or a = 32 Or a = 11 Then a = 46
        value = value & Chr(a)
    Next
    asciival = value

End Function

1 个答案:

答案 0 :(得分:-1)

Dim System.Threading.Thread yourthread As New System.Threading.Thread(AddressOf yourfunction())
yourthread.Priority = System.Threading.Priority.Highest
yourthread.Start();

您可以在函数中创建一个循环,并在循环结束时添加System.Threading.Thread.Sleep(1000),使其像计时器一样工作。您可以通过此线程调用所有现有函数,甚至是计时器。

通过线程访问控件时要小心。

Invoke(Sub() yourcontrol.property = someproperty)