我的程序从串口获取高速数据,并且定时器读取它,当定时器获得值后,定时器被禁用,并且代码执行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
当你不断向RichTextBox添加文本并且永远不会删除任何东西,那么过了一段时间后会变得非常昂贵。 RTB必须不断重新分配其内部缓冲区并将现有文本复制到其中。 StringBuilder存在以帮助字符串的基本原因。 RTB没有类似的东西,因此您必须确保自己删除旧文本。 –
THX的答复,我换成RTB与StringBuilder的:昏暗get_buffer作为新的StringBuilder get_buffer.Remove(0,get_buffer.Length) get_buffer.Append(newCommand&vbCrLf) 它imporved性能点点,但没有这么多 –
任何其他想法,也许尝试使用backgroundworker或其他? –