/// <summary>
        ///     加载串口
        /// </summary>
        /// <param name="SerialDataReceivedEventHandlerX">串口数据接收事件处理器扩展</param>
        /// <param name="BeforeOpen">尝试打开串口前操作</param>
        /// <param name="OpenSuccess">尝试打开串口成功操作</param>
        /// <param name="OpenError">尝试打开串口失败操作</param>
        /// <param name="StillOpen">仍处于打开状态操作</param>
        /// <param name="Disconnect">已经断开操作</param>
        /// <param name="BeforeReOpen">尝试重新打开串口前操作</param>
        /// <param name="ReOpenSuccess">尝试重新打开串口成功操作</param>
        /// <param name="ReOpenError">尝试重新打开串口失败操作</param>
        /// <param name="AfterOpen">串口打开后操作</param>
        public void Load
        (
            SerialDataReceivedEventHandlerX SerialDataReceivedEventHandlerX,
            BeforeOpen BeforeOpen,
            OpenSuccess OpenSuccess,
            OpenError OpenError,
            StillOpen StillOpen,
            Disconnect Disconnect,
            BeforeReOpen BeforeReOpen,
            ReOpenSuccess ReOpenSuccess,
            ReOpenError ReOpenError,
            AfterOpen AfterOpen
        )
        {
            if (serialPorts != null)
            {
                Release();
            }
            List <Dictionary <String, String> > configs = JSONFileReader.ReadArray(GetConfigFileName());

            serialPorts = new List <SerialPortX>(configs.Capacity);
            foreach (Dictionary <String, String> config in configs)
            {
                SerialPortX serialPort = new SerialPortX(config);
                serialPort.Start(
                    SerialDataReceivedEventHandlerX,
                    BeforeOpen,
                    OpenSuccess,
                    OpenError,
                    StillOpen,
                    Disconnect,
                    BeforeReOpen,
                    ReOpenSuccess,
                    ReOpenError,
                    AfterOpen
                    );
                serialPorts.Add(serialPort);
            }
        }
        private int byteLength   = 0;  // 部分响应信息字节长度

        /// <summary>
        ///     开始打开串口
        /// </summary>
        /// <param name="SerialDataReceivedEventHandlerX">串口数据接收事件处理器扩展</param>
        /// <param name="BeforeOpen">尝试打开串口前操作</param>
        /// <param name="OpenSuccess">尝试打开串口成功操作</param>
        /// <param name="OpenError">尝试打开串口失败操作</param>
        /// <param name="StillOpen">仍处于打开状态操作</param>
        /// <param name="Disconnect">已经断开操作</param>
        /// <param name="BeforeReOpen">尝试重新打开串口前操作</param>
        /// <param name="ReOpenSuccess">尝试重新打开串口成功操作</param>
        /// <param name="ReOpenError">尝试重新打开串口失败操作</param>
        /// <param name="AfterOpen">串口打开后操作</param>
        internal void Start(
            SerialDataReceivedEventHandlerX SerialDataReceivedEventHandlerX,
            BeforeOpen BeforeOpen,
            OpenSuccess OpenSuccess,
            OpenError OpenError,
            StillOpen StillOpen,
            Disconnect Disconnect,
            BeforeReOpen BeforeReOpen,
            ReOpenSuccess ReOpenSuccess,
            ReOpenError ReOpenError,
            AfterOpen AfterOpen
            )
        {
            // 设置串口数据接收事件处理器
            serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler((sender, e) =>
            {
                if (IsClosed)
                {
                    return;
                }
                byte[] readedBytes = new byte[serialPort.BytesToRead];
                int byteLength     = readedBytes.Length;
                if (byteLength == 0)
                {
                    CMDQueue.CancelCurrentCMD();
                    return;
                }
                serialPort.Read(readedBytes, 0, byteLength);
                String hexString = HexUtils.BytesToHexString(readedBytes, true).Trim();
                if ("".Equals(hexString))
                {
                    CMDQueue.CancelCurrentCMD();
                    return;
                }
                if (ModbusUtils.IsFullCmd(hexString))
                {
                    if (useCMDQueue)
                    {
                        CMDQueue.FinishCurrentCMD(hexString);
                    }
                    SerialDataReceivedEventHandlerX?.Invoke(this.sid, this.portName, hexString);
                    this.hexString  = "";
                    this.byteLength = 0;
                }
                else
                {
                    this.hexString  += " " + hexString;
                    this.hexString   = this.hexString.Trim();
                    this.byteLength += byteLength;
                    if (ModbusUtils.IsFullCmd(this.hexString))
                    {
                        if (useCMDQueue)
                        {
                            CMDQueue.FinishCurrentCMD(hexString);
                        }
                        SerialDataReceivedEventHandlerX?.Invoke(this.sid, this.portName, this.hexString);
                        this.hexString  = "";
                        this.byteLength = 0;
                    }
                }
            });

            // 每100毫秒执行一次指令队列
            if (useCMDQueue)
            {
                CMDQueue = new SerialPortCMDQueue(this.sid, this.portName, serialPort);
                CMDQueue.Start();
            }

            BeforeOpen?.Invoke(this.sid, this.portName);      // 尝试打开串口前操作
            if (this.Open())                                  // 尝试打开串口
            {
                OpenSuccess?.Invoke(this.sid, this.portName); // 尝试打开串口成功操作
                OpenStatus = true;
                if (AfterOpen != null)
                {
                    AfterOpenEventHandlerListenerTimer = new Timer((obj) =>
                    {
                        AfterOpen(this.sid, this.portName);// 串口打开后操作
                    }, null, 0, this.afterOpenEventHandlerPeriod);
                }
            }
            else
            {
                OpenError?.Invoke(this.sid, this.portName);// 尝试打开串口失败操作
                OpenStatus = null;
                if (AfterOpen != null)
                {
                    AfterOpenEventHandlerListenerTimer = new Timer((obj) =>
                    {
                        if (IsClosed)
                        {
                            return;
                        }
                        AfterOpen(this.sid, this.portName);// 串口打开后操作
                    }, null, Timeout.Infinite, Timeout.Infinite);
                }
            }
            // 无论打开成功与否,后续都需要监听该串口是否处于打开状态。
            OpenStatusListenerTimer = new Timer((o) =>
            {
                if (IsClosed)
                {
                    return;
                }
                switch (OpenStatus)                                         // 上一次的串口打开状态
                {
                case null:                                                  // 首次打开串口失败
                case false:                                                 // 后续打开串口失败
                    {
                        BeforeReOpen?.Invoke(this.sid, this.portName);      // 尝试重新打开串口前操作
                        if (this.Open())                                    // 尝试重新打开串口
                        {
                            ReOpenSuccess?.Invoke(this.sid, this.portName); // 尝试重新打开串口成功操作
                            OpenStatus = true;
                            if (AfterOpen != null)
                            {
                                AfterOpenEventHandlerListenerTimer.Change(0, this.afterOpenEventHandlerPeriod);    // 重新开启计时器
                            }
                        }
                        else
                        {
                            ReOpenError?.Invoke(this.sid, this.portName);    // 尝试重新打开串口失败
                            OpenStatus = false;
                        }
                    }
                    break;

                case true:                                              // 首次或后续打开串口成功
                    {
                        if (serialPort.IsOpen)                          // 仍处于打开状态
                        {
                            StillOpen?.Invoke(this.sid, this.portName); // 仍处于打开状态操作
                            OpenStatus = true;
                        }
                        else                                             // 已经断开
                        {
                            Disconnect?.Invoke(this.sid, this.portName); // 已经断开操作
                            OpenStatus = false;
                            if (AfterOpen != null)
                            {
                                AfterOpenEventHandlerListenerTimer.Change(Timeout.Infinite, Timeout.Infinite);    // 暂停计时器
                            }
                        }
                    }
                    break;
                }
            }, null, this.checkOpenStatusPeriod, this.checkOpenStatusPeriod);
        }