2017-08-31 140 views
0

我的程序从串口获取高速数据,并且定时器读取它,当定时器获得值后,定时器被禁用,并且代码执行sting操作,其中增加了从com早期接受到listview的值。问题是,UI线程并不完全冻结,但它似乎laggy当我拖动窗体,也就是说,每次在subitem.text上添加+1的代码是不光滑的。Timer1冻结UI线程

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

这是为什么作为计时器知道其外币自己的线程,它shouldnot冻结的UI(我不能摆脱定时器,becsouse其neccesary接受来自串行正确的数据) 任何提示吗?我试着调用,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 
+0

当你不断向RichTextBox添加文本并且永远不会删除任何东西,那么过了一段时间后会变得非常昂贵。 RTB必须不断重新分配其内部缓冲区并将现有文本复制到其中。 StringBuilder存在以帮助字符串的基本原因。 RTB没有类似的东西,因此您必须确保自己删除旧文本。 –

+0

THX的答复,我换成RTB与StringBuilder的:昏暗get_buffer作为新的StringBuilder get_buffer.Remove(0,get_buffer.Length) get_buffer.Append(newCommand&vbCrLf) 它imporved性能点点,但没有这么多 –

+0

任何其他想法,也许尝试使用backgroundworker或其他? –

回答

-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) 
+0

你真的不应该改变线程的优先级。系统计划“正常优先级” - 线程为每个线程提供相当数量的处理器时间,以便所有线程均可平稳运行。将优先级切换为高可能会导致其他进程挨饿。 –

+0

Afnan sry,我没有得到它 –

+0

尝试改变(AddressOf yourfunction())到(AddressOf parseData()) 并运行我的代码,你明白了。 parseData是你的功能,而不是别的 –