none
VB.NET2008开发的串口通讯程序界面出现假死现象,并且有时委托不成功,求解? RRS feed

  • 问题

  • 各位大侠,我用VB.NET2008做的串口通讯程序在启动程序后第一次打开串口能正常通讯,然后关掉串口再打开串口就会出现界面假死,而且有时发现委托不成功,程序没有执行到委托函数中去。下面是我的串口通讯部分的代码,请指教,谢谢!

        Private Sub DataReceived() Handles SerialPort1.DataReceived
            Dim num As Integer = 0 ' = Me.SerialPort1.BytesToRead
            Dim Receive_array(num - 1) As Byte
            Dim stringR As String = ""
            Thread.Sleep(3)
            Try

                Dim inDataLen As Integer = SerialPort1.BytesToRead()
                If inDataLen > 0 Then
                    Dim inBytes(inDataLen - 1) As Byte, bytes As Byte
                    Dim strHex As String = ""
                    SerialPort1.Read(inBytes, 0, inDataLen)
                    For Each bytes In inBytes
                        If bytes > 15 Then
                            RecvString = RecvString & Hex(bytes)
                        Else
                            RecvString = RecvString & 0 & Hex(bytes)
                        End If
                    Next

                    Invoke(New EventHandler(AddressOf ONMLoadA), Nothing) '使用委托方式显示接收到的字符串
                    Debug.WriteLine(RecvString)
                End If
                '=========================================================================
            Catch ex As Exception
                ' MsgBox("DataReceive部分" & ex.Message)
            End Try
        End Sub

    2013年12月14日 9:43

答案

  • 改成这样试试。。

        Private Sub DataReceived() Handles SerialPort1.DataReceived
            'Dim num As Integer = 0 ' = Me.SerialPort1.BytesToRead
            'Dim Receive_array(num - 1) As Byte
            'Dim stringR As String = ""
            'Thread.Sleep(3)  不应该在这个事件里面使用这个阻塞线程。
    
            Dim Temp As String = ""
            Try
    
                Dim inDataLen As Integer = SerialPort1.BytesToRead()
                If inDataLen > 0 Then
                    Dim inBytes(inDataLen - 1) As Byte, bytes As Byte
                    Dim strHex As String = ""
                    SerialPort1.Read(inBytes, 0, inDataLen)
                    For Each bytes As Byte In inBytes
                        Temp &= String.Format("{0:X2}", bytes)
                    Next
    
                    BeginInvoke(New EventHandler(AddressOf ONMLoadA), Temp) '使用委托方式显示接收到的字符串
                    Debug.WriteLine(Temp)
                End If
                '=========================================================================
            Catch ex As Exception
                ' MsgBox("DataReceive部分" & ex.Message)
            End Try
        End Sub
    
        Private Sub ONMLoadA(sender As Object, e As EventArgs)
            RecvString &= sender.ToString() '合并之前接收到的字符串
            'TODO:显示你的字符串。
        End Sub

    2013年12月14日 14:54
  • 或者你可以这样写

    '若 With {.WorkerSupportsCancellation = True} VS2008不支持,请在启动线程前设置该属性为True 
        Private WithEvents BWReceive As New BackgroundWorker() With {.WorkerSupportsCancellation = True}
        Private IsExitLoop As Boolean = False
        Private RecvData As String = ""
    
        Private Sub OpenPort()
            If Me.SerialPort1.IsOpen Or BWReceive.IsBusy Then Return
            Try
                Me.SerialPort1.Open()
    
                '清除所有缓冲区
                Me.SerialPort1.DiscardInBuffer()
                Me.SerialPort1.DiscardOutBuffer()
    
                IsExitLoop = False
                BWReceive.RunWorkerAsync() '启动读取线程
            Catch ex As Exception
                MsgBox("打来串口出错:" & ex.Message)
            End Try
        End Sub
    
        Private Sub ClosePort()
            IsExitLoop = True '通知线程终止循环读取串口数据
        End Sub
    
        '任务处理事件
        Private Sub BWReceive_DoWork(sender As Object, e As DoWorkEventArgs) Handles BWReceive.DoWork
    
            Do While Not IsExitLoop '若没接收到停止读取信号,就一直读取下去。
    
                If Me.SerialPort1.IsOpen AndAlso Me.SerialPort1.BytesToRead() > 0 Then
                    Dim Temp As String = ""
                    Dim Buff(2047) As Byte '根据你设置的ReadBufferSize而定
                    Dim RecvLen As Integer = Me.SerialPort1.Read(Buff, 0, 2048)
                    If RecvLen > 0 Then
                        For i As Integer = 0 To RecvLen - 1
                            Temp &= String.Format("{0:X2}", Buff(i)) '注意如果这里的字节数很多,会消耗很多处理时间。
                        Next
                        BeginInvoke(New EventHandler(AddressOf DataReceived), Temp) '将这次读取到的数据显示到主线程控件
                    End If
                End If
    
                System.Threading.Thread.Sleep(5)
            Loop
        End Sub
    
        '任务完成事件
        Private Sub BWReceive_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BWReceive.RunWorkerCompleted
            Me.SerialPort1.Close()
        End Sub
    
        Private Sub DataReceived(sender As Object, e As EventArgs)
            'TODO:在此添加数据处理代码
            RecvData &= sender.ToString() '将接收到的数据合并到之前接收到的数据之中。
    
        End Sub

    2013年12月14日 15:28

全部回复

  • 改成这样试试。。

        Private Sub DataReceived() Handles SerialPort1.DataReceived
            'Dim num As Integer = 0 ' = Me.SerialPort1.BytesToRead
            'Dim Receive_array(num - 1) As Byte
            'Dim stringR As String = ""
            'Thread.Sleep(3)  不应该在这个事件里面使用这个阻塞线程。
    
            Dim Temp As String = ""
            Try
    
                Dim inDataLen As Integer = SerialPort1.BytesToRead()
                If inDataLen > 0 Then
                    Dim inBytes(inDataLen - 1) As Byte, bytes As Byte
                    Dim strHex As String = ""
                    SerialPort1.Read(inBytes, 0, inDataLen)
                    For Each bytes As Byte In inBytes
                        Temp &= String.Format("{0:X2}", bytes)
                    Next
    
                    BeginInvoke(New EventHandler(AddressOf ONMLoadA), Temp) '使用委托方式显示接收到的字符串
                    Debug.WriteLine(Temp)
                End If
                '=========================================================================
            Catch ex As Exception
                ' MsgBox("DataReceive部分" & ex.Message)
            End Try
        End Sub
    
        Private Sub ONMLoadA(sender As Object, e As EventArgs)
            RecvString &= sender.ToString() '合并之前接收到的字符串
            'TODO:显示你的字符串。
        End Sub

    2013年12月14日 14:54
  • 或者你可以这样写

    '若 With {.WorkerSupportsCancellation = True} VS2008不支持,请在启动线程前设置该属性为True 
        Private WithEvents BWReceive As New BackgroundWorker() With {.WorkerSupportsCancellation = True}
        Private IsExitLoop As Boolean = False
        Private RecvData As String = ""
    
        Private Sub OpenPort()
            If Me.SerialPort1.IsOpen Or BWReceive.IsBusy Then Return
            Try
                Me.SerialPort1.Open()
    
                '清除所有缓冲区
                Me.SerialPort1.DiscardInBuffer()
                Me.SerialPort1.DiscardOutBuffer()
    
                IsExitLoop = False
                BWReceive.RunWorkerAsync() '启动读取线程
            Catch ex As Exception
                MsgBox("打来串口出错:" & ex.Message)
            End Try
        End Sub
    
        Private Sub ClosePort()
            IsExitLoop = True '通知线程终止循环读取串口数据
        End Sub
    
        '任务处理事件
        Private Sub BWReceive_DoWork(sender As Object, e As DoWorkEventArgs) Handles BWReceive.DoWork
    
            Do While Not IsExitLoop '若没接收到停止读取信号,就一直读取下去。
    
                If Me.SerialPort1.IsOpen AndAlso Me.SerialPort1.BytesToRead() > 0 Then
                    Dim Temp As String = ""
                    Dim Buff(2047) As Byte '根据你设置的ReadBufferSize而定
                    Dim RecvLen As Integer = Me.SerialPort1.Read(Buff, 0, 2048)
                    If RecvLen > 0 Then
                        For i As Integer = 0 To RecvLen - 1
                            Temp &= String.Format("{0:X2}", Buff(i)) '注意如果这里的字节数很多,会消耗很多处理时间。
                        Next
                        BeginInvoke(New EventHandler(AddressOf DataReceived), Temp) '将这次读取到的数据显示到主线程控件
                    End If
                End If
    
                System.Threading.Thread.Sleep(5)
            Loop
        End Sub
    
        '任务完成事件
        Private Sub BWReceive_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BWReceive.RunWorkerCompleted
            Me.SerialPort1.Close()
        End Sub
    
        Private Sub DataReceived(sender As Object, e As EventArgs)
            'TODO:在此添加数据处理代码
            RecvData &= sender.ToString() '将接收到的数据合并到之前接收到的数据之中。
    
        End Sub

    2013年12月14日 15:28