我的程序从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
答案 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)