C#串口通讯 ,我这个读取正常,但是写入是就有问题,要不卡顿,要不就写不进去,请大家指导指导

我这个串口程序读取的时候正常,但是写入时就有问题,或者说我的思路有问题,请教指

namespace 串口
{
public partial class Form1 : Form
{
private SerialPort MyModbus;

    private byte[] OutputStatus;
    private byte[] InputStatus;
    private byte[] HoldRegister;
    private byte[] InputeRegister;

    public Form1()
    {
        InitializeComponent();

        Control.CheckForIllegalCrossThreadCalls = false;
    }

    #region 连接关闭串口
    private void btn_Connect_Click(object sender, EventArgs e)
    {
        if (btn_Connect.Text == "Connect")
        {
            try
            {
                MyModbus = new SerialPort(cbx_Address.Text, 9600, Parity.None, 8, StopBits.One);
                if (MyModbus.IsOpen)
                {
                    MyModbus.Close();
                }
                MyModbus.Open();
                btn_Connect.Text = "DisConnect";
                MessageBox.Show("连接成功!!!", "提示");

                Task.Run(new Action(() =>
                {
                    while (true)
                    {
                        try
                        {
                            OutputStatus = GetOutputStatus(1, 0x01, 0, 10);
                            InputStatus = GetOutputStatus(1, 0x02, 0, 10);
                            HoldRegister = GetHoldRegister(1, 0x03, 0, 10);
                       
                               

                            Task.Run(new Action(() =>
                            {
                                bool[] b = GetByteArrayToBoolArray(OutputStatus, 10);
                                string str = GetBoolArrayToString(b, 10);

                                bool[] bb = GetByteArrayToBoolArray(InputStatus, 10);
                                string st = GetBoolArrayToString(bb, 10);
                                txt_in.Text = str + "\r\n" + st; ;

                                ushort us = GetByteArrayToUshort(HoldRegister, 0);
                                txt_out.Text = (Convert.ToString(us));
                            }));
                           
                        }
                        catch (Exception)
                        {
                            return;
                        }
                    }
                }));

            }
            catch (Exception ex)
            {
                MessageBox.Show("连接失败!!!" + ex.Message, "提示");
            }
        }
        else
        {
          
            MyModbus.Close();
            btn_Connect.Text = "Connect";

        }
    }
    #endregion

    #region 串口数据写入
    private void btn_Set_Click(object sender, EventArgs e)
    {
        SetOutputStatus(1, 0x05, Convert.ToUInt16(txt_Set.Text), true);
    }

   

    #endregion

    #region 读写数据

    /// <summary>
    /// 读取输入输出线圈状态(0x01)(0x02)
    /// </summary>
    /// <param name="Address">从站地址</param>
    /// <param name="FunctionCode">功能码</param>
    /// <param name="StartAddress">起始地址</param>
    /// <param name="Length">数据长度</param>
    /// <returns>字节数组</returns>
    private byte[] GetOutputStatus(byte Address, byte FunctionCode, ushort StartAddress, ushort Length)
    {
        //1、拼接报文
        List<byte> SendComand = new List<byte>();

        SendComand.Add(Address);//从站地址

        SendComand.Add(FunctionCode);//功能码

        SendComand.Add((byte)(StartAddress / 256)); //起始地址
        SendComand.Add((byte)(StartAddress % 256));

        SendComand.Add((byte)(Length / 256)); //数据长度
        SendComand.Add((byte)(Length % 256));

        SendComand.AddRange(CRC16_Check(SendComand.ToArray()));//CRC校验

        //2、发送报文

        MyModbus.Write(SendComand.ToArray(), 0, SendComand.Count);
        //3、接收报文

        Thread.Sleep(50);//延时20MS
        int ReadLength = MyModbus.BytesToRead;//获取接收缓冲区大小
        byte[] ReadBuffer = new byte[ReadLength];//创建数据缓冲区

        MyModbus.Read(ReadBuffer, 0, ReadBuffer.Length);//将数据读取到数据缓冲区

        //4、验证报文
        int bitLength = Length % 8 == 0 ? Length / 8 : Length / 8 + 1;//返回数据字节数

        byte[] DataValue = new byte[bitLength];//读取的数据
        if (ReadBuffer.Length == 5 + bitLength)
        {
            if (CheckCRC(ReadBuffer))
            {
                //5、解析报文

                Array.Copy(ReadBuffer, 3, DataValue, 0, DataValue.Length);
            }
        }

        return DataValue;
    }
    /// <summary>
    /// 读取保持寄存器(0x03)输入寄存器(0x04)
    /// </summary>
    /// <param name="Address">从站地址</param>
    /// <param name="FunctionCode">功能码</param>
    /// <param name="StartAddress">起始地址</param>
    /// <param name="Length">读取长度</param>
    /// <returns>字节数组</returns>
    private byte[] GetHoldRegister(byte Address, byte FunctionCode, ushort StartAddress, ushort Length)
    {
        //1、拼接报文
        List<byte> SendComand = new List<byte>();

        SendComand.Add(Address);//从站地址

        SendComand.Add(FunctionCode);//功能码

        SendComand.Add((byte)(StartAddress / 256)); //起始地址
        SendComand.Add((byte)(StartAddress % 256));

        SendComand.Add((byte)(Length / 256)); //数据长度
        SendComand.Add((byte)(Length % 256));

        SendComand.AddRange(CRC16_Check(SendComand.ToArray()));//CRC校验

        //2、发送报文

        MyModbus.Write(SendComand.ToArray(), 0, SendComand.Count);
        //3、接收报文

        Thread.Sleep(50);//延时20MS


        int ReadLength = MyModbus.BytesToRead;//获取接收缓冲区大小
        byte[] ReadBuffer = new byte[ReadLength];//创建数据缓冲区

        MyModbus.Read(ReadBuffer, 0, ReadBuffer.Length);//将数据读取到数据缓冲区

        //4、验证报文
        int ByteLength = Length * 2;//返回数据字节数

        byte[] DataValue = new byte[ByteLength];//读取的数据

        if (ReadBuffer.Length == 5 + ByteLength)
        {
            if (CheckCRC(ReadBuffer))
            {
                //5、解析报文

                Array.Copy(ReadBuffer, 3, DataValue, 0, DataValue.Length);
            }
        }

        return DataValue;

    }

    /// <summary>
    /// 写单个线圈(0x05)
    /// </summary>
    /// <param name="Address">从站地址</param>
    /// <param name="FunctionCode">功能码</param>
    /// <param name="SetAddress">写入地址</param>
    /// <param name="SetValue">写入值</param>
    /// <returns>字节数组</returns>
    private bool SetOutputStatus(byte Address, byte FunctionCode, ushort SetAddress, bool SetValue)
    {
        ushort Value = 0;
        if (SetValue == true)
        {
            Value = 0xff00;
        }
        else
        {
            Value = 0;
        }

        //1、拼接报文
        List<byte> SendComand = new List<byte>();

        SendComand.Add(Address);//从站地址

        SendComand.Add(FunctionCode);//功能码

        SendComand.Add((byte)(SetAddress / 256)); //写入地址
        SendComand.Add((byte)(SetAddress % 256));

        SendComand.Add((byte)(Value / 256)); //数据长度
        SendComand.Add((byte)(Value % 256));

        SendComand.AddRange(CRC16_Check(SendComand.ToArray()));//CRC校验

        //2、发送报文

        MyModbus.Write(SendComand.ToArray(), 0, SendComand.Count);
        //3、接收报文

        Thread.Sleep(50);//延时20MS


        int ReadLength = MyModbus.BytesToRead;//获取接收缓冲区大小
        byte[] ReadBuffer = new byte[ReadLength];//创建数据缓冲区

        MyModbus.Read(ReadBuffer, 0, ReadBuffer.Length);//将数据读取到数据缓冲区

        //4、验证报文


        if (ReadBuffer.Length == 8 && CheckCRC(ReadBuffer))
        {
            //5、解析报文

            return true;
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 写单个寄存器(0x06)
    /// </summary>
    /// <param name="Address">从站地址</param>
    /// <param name="FunctionCode">功能码</param>
    /// <param name="SetAddress">写入地址</param>
    /// <param name="SetValue">写入值</param>
    /// <returns>字节数组</returns>
    private bool SetHoldRegister(byte Address, byte FunctionCode, ushort SetAddress, ushort SetValue)
    {
        //1、拼接报文
        List<byte> SendComand = new List<byte>();

        SendComand.Add(Address);//从站地址

        SendComand.Add(FunctionCode);//功能码

        SendComand.Add((byte)(SetAddress / 256)); //起始地址
        SendComand.Add((byte)(SetAddress % 256));

        SendComand.Add((byte)(SetValue / 256)); //数据长度
        SendComand.Add((byte)(SetValue % 256));

        SendComand.AddRange(CRC16_Check(SendComand.ToArray()));//CRC校验

        //2、发送报文

        MyModbus.Write(SendComand.ToArray(), 0, SendComand.Count);
        //3、接收报文

        Thread.Sleep(50);//延时20MS


        int ReadLength = MyModbus.BytesToRead;//获取接收缓冲区大小
        byte[] ReadBuffer = new byte[ReadLength];//创建数据缓冲区

        MyModbus.Read(ReadBuffer, 0, ReadBuffer.Length);//将数据读取到数据缓冲区

        //4、验证报文

        if (ReadBuffer.Length == 8 && CheckCRC(ReadBuffer))
        {
            //5、解析报文

            return true;
        }
        else
        {
            return false;
        }
    }
    #endregion

    #region CheckCRC
    /// <summary>
    /// 接收报文CRC验证
    /// </summary>
    /// <param name="buffer">接收的字节数组</param>
    /// <returns>布尔值(true数据正常/false数据异常)</returns>
    private bool CheckCRC(byte[] buffer)
    {
        if (buffer == null) return false;
        if (buffer.Length <= 2) return false;
        int length = buffer.Length;
        byte[] Value = new byte[length - 2];
        Array.Copy(buffer, 0, Value, 0, Value.Length);

        byte[] CRCbuf = CRC16_Check(Value);

        return CRCbuf[0] == buffer[length - 2] && CRCbuf[1] == buffer[length - 1];
    }

    #endregion

    #region CRC校验
    /// <summary>
    /// CRC16校验
    /// </summary>
    /// <param name="data">字节数组</param>
    /// <returns>16位字节数组</returns>
    public static byte[] CRC16_Check(byte[] data)
    {
        byte CRC16Lo;
        byte CRC16Hi;   //CRC寄存器 
        byte CL; byte CH;       //多项式码&HA001 
        byte SaveHi; byte SaveLo;
        byte[] tmpData;
        //int I;
        int Flag;
        CRC16Lo = 0xFF;
        CRC16Hi = 0xFF;
        CL = 0x01;
        CH = 0xA0;
        tmpData = data;
        for (int i = 0; i < tmpData.Length; i++)
        {
            CRC16Lo = (byte)(CRC16Lo ^ tmpData[i]); //每一个数据与CRC寄存器进行异或 
            for (Flag = 0; Flag <= 7; Flag++)
            {
                SaveHi = CRC16Hi;
                SaveLo = CRC16Lo;
                CRC16Hi = (byte)(CRC16Hi >> 1);      //高位右移一位 
                CRC16Lo = (byte)(CRC16Lo >> 1);      //低位右移一位 
                if ((SaveHi & 0x01) == 0x01) //如果高位字节最后一位为1 
                {
                    CRC16Lo = (byte)(CRC16Lo | 0x80);   //则低位字节右移后前面补1 
                }             //否则自动补0 
                if ((SaveLo & 0x01) == 0x01) //如果LSB为1,则与多项式码进行异或 
                {
                    CRC16Hi = (byte)(CRC16Hi ^ CH);
                    CRC16Lo = (byte)(CRC16Lo ^ CL);
                }
            }
        }
        byte[] ReturnData = new byte[2];
        ReturnData[0] = CRC16Lo;       //CRC高位 
        ReturnData[1] = CRC16Hi;       //CRC低位 
        return ReturnData;
    }
    #endregion

    #region 数据转换
    /// <summary>
    /// 将字节数组转换为布尔数组
    /// </summary>
    /// <param name="buffer">字节数组</param>
    /// <param name="Length">布尔数组长度</param>
    /// <returns>布尔数组</returns>
    public static bool[] GetByteArrayToBoolArray(byte[] buffer, int Length)
    {
        bool[] b = new bool[Length];
        if (Length <= buffer.Length * 8)
        {
            BitArray array = new BitArray(buffer);
            for (int i = 0; i < Length; i++)
            {
                b[i] = array[i];
            }
            return b;
        }
        else
        {
            return null;
        }
    }

    /// <summary>
    /// 字节数组转换为16位无符号整型
    /// </summary>
    /// <param name="buffer">字节数组</param>
    /// <param name="index">起始字节索引</param>
    /// <returns>16位无符号短整型</returns>
    public static ushort GetByteArrayToUshort(byte[] buffer, int index = 0)
    {
        byte[] data = new byte[2];
        Array.Copy(buffer, index, data, 0, 2);
        data = data.Reverse().ToArray();
        ushort us = BitConverter.ToUInt16(data, 0);
        return us;
    }

    /// <summary>
    /// 将布尔数组转换为字符串
    /// </summary>
    /// <param name="b">布尔数组</param>
    /// <param name="Count">数据个数</param>
    /// <returns>字符串</returns>
    public static string GetBoolArrayToString(bool[] b, int Count)
    {
        string str = string.Empty;
        if (b != null)
        {
            bool[] buffer = new bool[Count];
            Array.Copy(b, 0, buffer, 0, Count);

            for (int i = 0; i < Count; i++)
            {
                str += buffer[i].ToString() + " ";
            }
            return str;
        }
        else
        {
            return str = "转换失败!!!";
        }
    }



    #endregion

img