C#上位机软件再次连接失败

上位机软件使用C#进行编写。问题上位机第一次可以连接成功,但是在关掉后,第二次无法连接成功,但是在第一次关闭后,可以使用其他上位机软件使用该串口进行连接,并且在使用其他上位机软件进行关闭串口操作后,再次打开问题上位机软件,可以连接成功。请问,按照测试,串口应该已经被释放,其他上位机软件才能再次进行使用,但是问题上位机却无法二次进行连接,这属于什么问题?
代码如下:这种情况该如何解决?

namespace IonosphericScintillationMonitor.UI
{
public partial class ConnectNovatelReceiverStatusForm : Form
{
private string portName;
private int baudRate;

public ConnectNovatelReceiverStatusForm()
{
    InitializeComponent();
    this.FormBorderStyle = FormBorderStyle.FixedDialog;
    //this.ControlBox = false;//不显示最小、最大和关闭按钮   
    this.MinimizeBox = false;
    this.MaximizeBox = false;         
    this.StartPosition = FormStartPosition.CenterScreen;
    InitializeSerialPort();            
}

private void InitializeSerialPort()
{
    //注册表中与串口设置相关的名称/值对的名称
    const string PORTNAME_VALUE = "PortName";
    const string BAUDRATE_VALUE = "BaudRate";          

    string rootName = "HKEY_CURRENT_USER";
    string keyName = rootName + "\\" + "Software" + "\\"
         + "IonosphericScintillationMonitor" + "\\" + "ComSet";

    //读取注册表中串口的默认值
    try
    {
        this.portName = (string)Registry.GetValue(keyName, PORTNAME_VALUE, null);
        this.baudRate = Convert.ToInt32(Registry.GetValue(keyName, BAUDRATE_VALUE, null));                                
    }
    catch (SecurityException e)
    {
        BaseSupportTools.PrintExceptionMessage(e);
    }
    catch (IOException e)
    {
        BaseSupportTools.PrintExceptionMessage(e);
    }
    catch (ArgumentException e)
    {
        BaseSupportTools.PrintExceptionMessage(e);
    }            
}

public void CreateConnect()
{           
    SerialPort serialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);

    int failConnectCount = 0;
    try
    {
        serialPort.Open();
        bool isConnect = false;                
        this.prgConnectStatus.Value = 20;
        this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
        this.lblConnectStatus.Text = "以9600bps正在尝试连接中。。。";
        this.lblConnectStatus.Refresh();//lable控件立即刷新显示
        //以9600bps的默认速率进行首次连接
        while (!isConnect)
        {
            isConnect = TryConnect(serialPort);
            //间隔1s后重连或进行下一步
            System.Threading.Thread.Sleep(1000);
            failConnectCount++;
            if (failConnectCount > 20)
            {
                if (MessageBox.Show("Novatel接收机连接失败", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error) == DialogResult.OK)
                {
                    //彻底退出程序
                    System.Environment.Exit(0);
                }
            }
        }               
                  
        this.prgConnectStatus.Value = 40;
        this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
        this.lblConnectStatus.Text = "重置通信波特率为" + baudRate + "bps。。。";
        this.lblConnectStatus.Refresh();//lable控件立即刷新显示

        //重置通信速率为 baudRate bps
        TrySerialConfig(serialPort, baudRate);
        serialPort.Close();
        
        this.prgConnectStatus.Value = 60;
        this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
        this.lblConnectStatus.Text = "重置通信波特率为" + baudRate + "bps成功";
        this.lblConnectStatus.Refresh();//lable控件立即刷新显示
        System.Threading.Thread.Sleep(1500);
        
        this.prgConnectStatus.Value = 80;
        this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
        this.lblConnectStatus.Text = "以" + baudRate + "bps正在尝试重新连接中。。。";
        this.lblConnectStatus.Refresh();//lable控件立即刷新显示
        System.Threading.Thread.Sleep(1000);

        //以 baudRate bps的速率进行再次连接
        failConnectCount = 0;
        serialPort.BaudRate = baudRate;
        serialPort.Open();
        while (!isConnect)
        {
            isConnect = TryConnect(serialPort);
            //间隔1s后重连或进行下一步
            System.Threading.Thread.Sleep(1000);
            if (failConnectCount > 5)
            {
                if (MessageBox.Show("Novatel接收机连接失败", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error) == DialogResult.OK)
                {
                    //彻底退出程序
                    System.Environment.Exit(0);
                }
            }
        }

        //开启GPS、北斗系统和关闭GLONASS系统
        serialPort.WriteLine("assignall  gps  auto");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("assignall  beidou  auto");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("assignall  glonass  idle");
        System.Threading.Thread.Sleep(1000);
        //发送指令
        serialPort.WriteLine("log bestposb ontime 1");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("log bestvelb ontime 1");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("log ionutcb ontime 1");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("log psrdopb ontime 1");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("log satvis2b ontime 60");
        System.Threading.Thread.Sleep(1000);
        serialPort.WriteLine("log rangecmpb ontime 0.2");
        System.Threading.Thread.Sleep(1000);

        this.prgConnectStatus.Value = 100;
        this.prgConnectStatus.Refresh();//ProgressBar控件立即刷新显示
        this.lblConnectStatus.Text = "Novatel接收机连接成功!";
        this.lblConnectStatus.Refresh();//lable控件立即刷新显示
        serialPort.Close();//关闭串口
        System.Threading.Thread.Sleep(1000);
        this.Close();//关闭串口

    }
    catch (System.IO.IOException e)
    {
        BaseSupportTools.PrintExceptionMessage(e);
        MessageBox.Show("当前串口已被占用", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
        //彻底退出程序
        System.Environment.Exit(0);
    }
}

/// <summary>
/// 尝试以目前的串口设置连接Novatel接收机
/// </summary>
/// <param name="serialPort">串口实例</param>
/// <returns></returns>
private static bool TryConnect(SerialPort serialPort)
{
    serialPort.Write("log versionb once");//发送指令
    serialPort.Write("\r");
    serialPort.Write("\n");
    System.Threading.Thread.Sleep(1000);//延迟1s
    int bytesCount = serialPort.BytesToRead;
    int tempData = 0;
    bool isFindHeaderSync1 = false;
    bool isFindHeaderSync2 = false;
    bool isFindHeaderSync3 = false;
    bool isConnect = false;
    int headerLength = 0;
    int availableByteCount = 0;//有效字节计数   
    byte[] temp2Bytes = new byte[2];
    for (int ix = 0; ix < bytesCount; ix++)
    {
        tempData = serialPort.ReadByte();
        //寻找帧头
        if (!isFindHeaderSync1)
        {
            if (tempData == 0xAA)
            {
                isFindHeaderSync1 = true;
            }
        }
        else if ((isFindHeaderSync1) && (!isFindHeaderSync2))
        {
            if (tempData == 0x44)
            {
                isFindHeaderSync2 = true;
            }
        }
        else if ((isFindHeaderSync1) && (isFindHeaderSync2) && (!isFindHeaderSync3))
        {
            if (tempData == 0x12)
            {
                isFindHeaderSync3 = true;
                availableByteCount = 3;//帧头3个字节检测成功了
                continue;
            }
        }

        //判断帧头是否寻找成功
        if ((isFindHeaderSync1) && (isFindHeaderSync2) && (isFindHeaderSync3))
        {
            if (availableByteCount == 3)
            {
                headerLength = tempData;
                availableByteCount++;
            }
            else if (availableByteCount == 4)
            {
                temp2Bytes[0] = (byte)tempData;
                availableByteCount++;
            }
            else if (availableByteCount == 5)
            {
                temp2Bytes[1] = (byte)tempData;
                int messageId = BitConverter.ToInt16(temp2Bytes, 0);
                if (messageId == 37)//即VERSION
                {
                    isConnect = true;//连接成功                           
                }
                availableByteCount++;
            }

        }
    }
    return isConnect;
}

/// <summary>
/// 尝试重置Novatel接收机的波特率
/// </summary>
/// <param name="serialPort">串口实例</param>
/// <param name="baudRate">重置后的波特率</param>
/// <returns></returns>
private static bool TrySerialConfig(SerialPort serialPort, int baudRate)
{
    bool isSerialConfig = false;
    string command = "serialconfig com1 " + baudRate + " n 8 1 n on";
    serialPort.Write(command);//发送指令           
    serialPort.Write("\r");
    serialPort.Write("\n");
    System.Threading.Thread.Sleep(1000);//延迟1s
    bool isSendSuccess1 = false;
    bool isSendSuccess2 = false;
    bool isSendSuccess3 = false;
    int bytesCount = serialPort.BytesToRead;
    int tempData = 0;
    for (int ix = 0; ix < bytesCount; ix++)
    {
        tempData = serialPort.ReadByte();
        if (!isSendSuccess1)
        {
            //寻找'<'
            if (tempData == 0x3C)
            {
                isSendSuccess1 = true;
            }
        }
        else if ((isSendSuccess1) && (!isSendSuccess2))
        {
            //寻找'O'
            if (tempData == 0x4F)
            {
                isSendSuccess2 = true;
            }
        }
        else if ((isSendSuccess1) && (isSendSuccess2) && (!isSendSuccess3))
        {
            //寻找'K'
            if (tempData == 0x4B)
            {
                isSendSuccess3 = true;
            }
        }

        //判断“<OK”是否寻找成功
        if ((isSendSuccess1) && (isSendSuccess2) && (isSendSuccess3))
        {
            isSerialConfig = true;
        }
    }
    return isSerialConfig;
}

}
}

如果想要在本次连接成功关闭后,可以直接进行第二次连接并成功,应该如何进行代码修改?

这代码让你写的稀碎
主线程里各种发送接收也就罢了,怎么还频繁打开关闭串口
给你个例子自己下载了看吧
https://download.csdn.net/download/z65443344/8251513
此外,你执行了Open,如果没有报错,那么串口就已经打开了
你的问题大概率是出在tryconnect里面的逻辑有问题

逻辑倒是很清楚,你想自适应波特率
那么每次切换波特率的时候,先停止读取,同时清掉串口缓存。

伪代码,假设我们用pipeline方式

try
{
 串口检查pipeline(“Com1”)
   .add<波特率设置>(9600)  
   .add<波特率设置>(115200)
   .add<数据处理>()
}
catch
{
     未找到支持协议的串口
}

波特率设置伪代码

  if(pipecontext上下文.是否已经找到=false)
 {
         如果已经open,请close,同时清除串口缓存
        发送校验指令
      try
    {
       await 等待校验成功(超时设置) //伪代码,我们不仔细写了,明白意思就好
      如果成功收到校验把,上下文是否已经找到设置为true,
}
 catch
 {
        //如果超时,这里可以不处理,也可以在这里就把串口close,并清除串口缓存,看自己的想法
     //我个人会把这个写在这里,因为我打开的,我清理,本身应该如此
}
      next(上下文)
 }

这样,逻辑就清除的,各个检查模块自己按顺序检查自己的,能打开最后进入正常的数据处理模块,不能打开最后一个数据模块对外丢异常出去

职责库的可以用这个

相关说明在这里
https://github.com/ipvalverde/PipelineNet