SerialPort控件委托方式显示接收的字符串有关问题

SerialPort控件委托方式显示接收的字符串问题
Dim strData As String
 Dim mRecvByte() As Byte

Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
  Dim mSize As Integer = Me.SerialPort1.BytesToRead
  ReDim mRecvByte(mSize - 1)
  SerialPort1.Read(mRecvByte, 0, mSize)
  BeginInvoke(New EventHandler(AddressOf ONMLoadA), SerialPort1.BytesToRead()) '使用委托方式显示接收的字符串
End Sub

Sub ONMLoadA(ByVal sender As System.Object, ByVal e As System.EventArgs) '委托
  Dim i As Integer
  For i = 0 To mRecvByte.Length 'mSize - 1
  strData = strData & IIf(mRecvByte(i) > 15, Hex(mRecvByte(i)), "0" & Hex(mRecvByte(i))) & " "
  Next

  TextBox2.Text = strData '显示为16进制
  TextBox3.Text = Len(strData) / 3
 End Sub


1. 接收的数据,显示时,只有第一次接近正确值,然后就离真相越来越远
2. 代码运行中途,经常提示 红色部分 数组索引越界,有时一开始运行就报此错误
3. 求其他更好的解决方案

------解决方案--------------------
VB.NET code

Imports System.IO.Ports
Imports System.Text
Public Class Form1
    '声明一个通信端口对象,使用WithEvents关键字,以便可以引发事件
    Dim WithEvents RS232 As SerialPort
    '声明一个委派类,并声明符合函数参数有一个,而其型态是字符串
    Delegate Sub SetTextCallback(ByVal InputString As String)
    Dim inStr As String
    Dim i As Integer = 0
    '**************************************************************
    '表单的Load事件中先将所有的通信端口先列出来
    '将通信端口排序,并将第一个通信端口设为默认值
    '**************************************************************
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each sp As String In SerialPort.GetPortNames()
            cmbCOM.Items.Add(sp)
        Next
        cmbCOM.Sorted = True  '排序
        cmbCOM.SelectedIndex = 0 '第一个是默认选项
    End Sub

    '**************************************************************
    '『打开通信端口』按钮的Click事件
    '此事件将设定通信端口参数,并打开通信端口
    '**************************************************************
    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
        Dim mBaudRate As Integer
        Dim mParity As IO.Ports.Parity
        Dim mDataBit As Integer
        Dim mStopbit As IO.Ports.StopBits
        Dim mPortName As String

        mPortName = cmbCOM.SelectedItem.ToString   '欲打开的通信端口   
        mBaudRate = 9600   '通信速度
        mParity = Parity.Even  '同位位检查设定
        mDataBit = 7    '数据位设定值
        mStopbit = StopBits.Two '停止位设定值
        '建立一个通信端口对象
        RS232 = New IO.Ports.SerialPort(mPortName, mBaudRate, mParity, mDataBit, mStopbit)
        RS232.Encoding = Encoding.ASCII
        ''''  RS232.Encoding = Encoding.Unicode  '设定编码方式为Unicode,以便能显示中文
        If Not RS232.IsOpen Then  '尚未打开
            RS232.Open()  '打开通信端口
            RS232.ReceivedBytesThreshold = 1  '设定引发事件的阀值
            btnSend.Enabled = True  '致能传送按钮

        Else
            MsgBox("~~通信端口打开错误(通信端口已被打开)~~", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)
            End
        End If

    End Sub

    '**************************************************************
    '『传送』按钮的Click事件
    '将欲传送的字符串通过串行端口送出去
    '**************************************************************
    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
        RS232.Write(txtSend.Text)  '采用Write方法送出
    End Sub

    '**************************************************************
    '『关闭通信端口』按钮的Click事件
    '以Close方法关闭通信端口,并释放对象所占用的资源
    '**************************************************************
    Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click
        If RS232 Is Nothing OrElse Not RS232.IsOpen Then  '尚未打开
            MsgBox("~~通信端口尚未打开~~", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)
            Exit Sub
        End If
        RS232.Close()
        RS232 = Nothing  '释放资源
    End Sub

    '**************************************************************
    '『结束程序』按钮 的Click事件
    '此事件将设定通信端口参数,并打开通信端口
    '**************************************************************
    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        If Not RS232 Is Nothing Then  '判断是否已建立通信对象
            If RS232.IsOpen Then RS232.Close() '若已打开,就将其关闭
        End If
        End
    End Sub

    '**************************************************************
    '通信端口对象的DataReceived事件程序
    '当有数据超过ReceivedBytesThreshold属性设定值会引发此事件
    '接收的程序可以写在此事件程序中
    '处理数据的部份必须另外以委派(Delagate)类予以处理,否则将会产生错误
    '**************************************************************
    Private Sub RS232_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles RS232.DataReceived
        '在此范围内,不能直接将结果指定给txtReceive控制项的Text属性
        '原因是事件的引发在不同的执行绪
        If e.EventType <> SerialData.Chars Then Exit Sub '判断接收的数据是否为字符
        Dim inData As String = RS232.ReadExisting '取得字符串
        DisplayText(inData)  '显示数据
    End Sub

    '**************************************************************
    '委派子程序
    '处理上述通信端口的接收事件
    '由于欲将数据显示到接收文字框中,因此必须检查是否由另外的Thread
    '所呼叫的,若是,则必须先建立委派对象
    'Invoke用于在拥有控制项基础视窗控制代码的执行绪上执行委派
    '**************************************************************
    Private Sub DisplayText(ByVal comData As String)
        '如果呼叫txtReceive的是另外的执行绪,传回True
        Try
            If Me.txtReceive.InvokeRequired Then
                '利用委派型别建立委派对象,并指定委派的函数
                Dim d As New SetTextCallback(AddressOf ShowString)
                '用大括号 {} 括住初始值,藉以初始化阵列的值。
                Me.Invoke(d, New Object() {comData})  '以指定的引数清单叫用函数
            Else  '相同的执行绪
                ShowString(comData)   '将收到的数据填入接收文字框中
            End If
        Catch ex As Exception
            'MsgBox(ex.ToString)
        Finally

        End Try
    End Sub

    '**************************************************************
    '显示数据的函数
    '**************************************************************
    Private Sub ShowString(ByVal comData As String)

        '  Region(将数据存入缓冲)

        Dim s As String = comData
        Try
            If comData.Length < 13 Then Exit Sub
            s = comData.Substring(comData.IndexOf(Chr(2)), 10)       '判断首字符

            s = s.ToCharArray                      '转换成数组来理解
            If s(1) = "M" Then                     '判断是否稳定
                Label4.Text = "稳定"
            Else
                Label4.Text = "动态"
            End If
            s = s.Substring(3, 7)                   '分离出重量数据
            's = s(1) + s(2) + s(3) + s(4) + s(5) + s(6)
            s = Single.Parse(s)
            txtReceive.Text = s
        Catch ex As Exception

        Finally

        End Try
        ' end region

    End Sub

    '**************************************************************
    '通信端口的KeyPress事件,在此不让用户输入数据
    '**************************************************************
    Private Sub cmbCOM_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCOM.KeyPress
        e.KeyChar = ChrW(0)  '禁止用户在其中输入任何的文字
    End Sub
End Class