空引用:对象引用未设置为对象的实例

本文关键字:对象 实例 设置 引用 对象引用 | 更新日期: 2023-09-27 18:32:19

我有一个用于串行通信的代码,此代码将值从文本框发送到设备或im测试到另一台PC。但是当我按下"程序"按钮时,出现此错误。

System.NullReferenceException was unhandled
Object reference not set to an instance of an object.

我可以通过 try catch 捕获异常,但随后我不会将我的值发送到连接到我的端口的设备。

这是我的代码:

public partial class MainForm : Form
    {
        private Settings _settings;
        private SettingsIniFile _settingsIniFile = new SettingsIniFile();
        private StringList _baudratelist = new StringList();
        private StringList _systemPorts = new StringList();
        private StringList _comportList = new StringList();
        private Timer _comtimer = new Timer();
        private ComPort _comport;
        public MainForm()
        {
            InitializeComponent();
            SetBaudrate();
            LoadSettings(false);
            LoadTextBoxes();
            LoadComportName();
            _comtimer.Tick += OnComtimerOnTick;
            _comtimer.Interval = 2000;
            _comtimer.Start();

            LoadComportName();
            Thread.Sleep(1000);
            var portname = GetCurrentComPort();

            if (portname != null)
            {
                _comport = new ComPort("COM6", 9600);
            }

            //var portname = GetCurrentComPort();
        }
        private String GetCurrentComPort()
        {
            int index = _comPortComboBox.SelectedIndex;
            if (index < 0)
                return null;
            return _comportList[index];
        }

        private void OnComtimerOnTick(object sender, EventArgs args)
        {
            foreach (var item in SerialPort.GetPortNames())
            {
                if (!_systemPorts.Contains(item))
                {
                    _comtimer.Stop();
                    _systemPorts.Add(item);
                    LoadComportName();
                    //MessageBox.Show("The new device is connected to" + item);
                    _comtimer.Start();
                }
            }
        }
        private void LoadSettings(bool defaults)
        {
            SettingsIniFile iniFile = new SettingsIniFile();
            _settings = iniFile.LoadSettings(defaults);
        }
        private void SaveSettings()
        {
            SaveTextBoxes();
            _settingsIniFile.Save(_settings);
        }
        private void LoadTextBoxes()
        {
            //ACR
            _startRemovalTextBox.Text = _settings.AcrStartRemoval11;
            _removalTimeTextBox.Text = _settings.AcrRemovalTime12;
            _removalDelayTextBox.Text = _settings.AcrRemovalDelay13;
            //CLEANING
            _durCleaningTextbox.Text = _settings.CleanDurCleaning21;
            _timeValveOnTextbox.Text = _settings.CleanTimeValveOn22;
            _timeValveOffTextBox.Text = _settings.CleanTimeValveOff23;
            //CALIBRATE
            _contentLeftTextBox.Text = _settings.CalibrateContentLeft31;
            _calibrateLeftTextBox.Text = _settings.CalibrateCalibrateLeft33;
            _contentRightTextBox.Text = _settings.CalibrateContentRight32;
            _calibrateRightTextBox.Text = _settings.CalibrateCalibrateRight34;
            //CONDUCTIVITY
            _factorLeftTextBox.Text = _settings.ConductFactorLeft41;
            _offsetLeftTextBox.Text = _settings.ConductOffsetleft42;
            _factorRightTextBox.Text = _settings.ConductFactorRight43;
            _offsetRightTextBox.Text = _settings.ConductOffsetRight44;
            _levelLeftTextBox.Text = _settings.ConductLevelLeft45;
            _levelRightTextBox.Text = _settings.ConductLevelRight46;
            //GENERAL
            _typeOfValveTextBox.Text = _settings.GeneralTypeOfValve51;
            _indicatorTextBox.Text = _settings.GeneralIndicator52;
            _inverseOutputTextBox.Text = _settings.GeneralInverseOutput53;
            _restartTimeTextBox.Text = _settings.GeneralRestartTime54;
            _waterTimeTextBox.Text = _settings.GeneralWaterTime55;
            _gateDelayTextbox.Text = _settings.GeneralGateDelay56;
            //PULSATION
            _pulsationTextBox.Text = _settings.PulsationPulsationPm61;
            _ratioFrontTextBox.Text = _settings.PulsationSrRatioFront62;
            _ratioBackTextBox.Text = _settings.PulsationSrRatioBack63;
            _stimulationTextBox.Text = _settings.PulsationStimulationPm64;
            _stimFrontTextBox.Text = _settings.PulsationSrStimFront65;
            _stimBackTextBox.Text = _settings.PulsationSrStimBack66;
            _stimulationDurTextBox.Text = _settings.PulsationStimulationDur67;
            //return _settings;
        }
        private void SaveTextBoxes()
        {
            //ACR
            _settings.AcrStartRemoval11 = _startRemovalTextBox.Text;
            _settings.AcrRemovalTime12 = _removalTimeTextBox.Text;
            _settings.AcrRemovalDelay13 = _removalDelayTextBox.Text;
            //CLEANING
            _settings.CleanDurCleaning21 = _durCleaningTextbox.Text;
            _settings.CleanTimeValveOn22 = _timeValveOnTextbox.Text;
            _settings.CleanTimeValveOff23 = _timeValveOffTextBox.Text;
            //CALIBRATE
            _settings.CalibrateContentLeft31 = _contentLeftTextBox.Text;
            _settings.CalibrateCalibrateLeft33 = _calibrateLeftTextBox.Text;
            _settings.CalibrateContentRight32 = _contentRightTextBox.Text;
            _settings.CalibrateCalibrateRight34 = _calibrateRightTextBox.Text;
            //CONDUCTIVITY
            _settings.ConductFactorLeft41 = _factorLeftTextBox.Text;
            _settings.ConductOffsetleft42 = _offsetLeftTextBox.Text;
            _settings.ConductFactorRight43 = _factorRightTextBox.Text;
            _settings.ConductOffsetRight44 = _offsetRightTextBox.Text;
            _settings.ConductLevelLeft45 = _levelLeftTextBox.Text;
            _settings.ConductLevelRight46 = _levelRightTextBox.Text;
            //GENERAL
            _settings.GeneralTypeOfValve51 = _typeOfValveTextBox.Text;
            _settings.GeneralIndicator52 = _indicatorTextBox.Text;
            _settings.GeneralInverseOutput53 = _inverseOutputTextBox.Text;
            _settings.GeneralRestartTime54 = _restartTimeTextBox.Text;
            _settings.GeneralWaterTime55 = _waterTimeTextBox.Text;
            _settings.GeneralGateDelay56 = _gateDelayTextbox.Text;
            //PULSATION
            _settings.PulsationPulsationPm61 = _pulsationTextBox.Text;
            _settings.PulsationSrRatioFront62 = _ratioFrontTextBox.Text;
            _settings.PulsationSrRatioBack63 = _ratioBackTextBox.Text;
            _settings.PulsationStimulationPm64 = _stimulationTextBox.Text;
            _settings.PulsationSrStimFront65 = _stimFrontTextBox.Text;
            _settings.PulsationSrStimBack66 = _stimBackTextBox.Text;
            _settings.PulsationStimulationDur67 = _stimulationDurTextBox.Text;
        }

        private void DefaultSettingButtonClick(object sender, System.EventArgs e)
        {
            LoadSettings(true);
            LoadTextBoxes();
            SaveSettings();
            LoadComportName();
        }

        private void SendSettingsButtonClick(object sender, System.EventArgs e)
        {
            var availablePorts = _systemPorts;
            if (availablePorts != null && availablePorts.Any())
            {
               SaveSettings();
               SendMessageTest();
            }
            else
            {
                _comPortComboBox.Text = "No Ports are available";
            }
        }
        private void LoadComportName()
        {
            var availablePorts = _systemPorts;
            _comPortComboBox.DataSource = null;

            if (availablePorts != null && availablePorts.Any())
            {
                _comPortComboBox.DataSource = availablePorts;
            }
            else
            {
                _comPortComboBox.Text = "No Ports are available";
            }
        }
        private void SetBaudrate()
        {
            _baudratelist.Add("4600");
            _baudratelist.Add("9600");
            _baudratelist.Add("19200");
        }
        private void SendMessageTest()
        {
            var Acrcontent = "[" + _acrNameLabel.Text + "]" + "'r'n" + _acrIdLabel11.Text + _startRemovalTextBox.Text + "'r'n"
                                 + _acrIdLabel12.Text + _removalTimeTextBox.Text + "'r'n" + _acrIdLabel13.Text +
                            _removalDelayTextBox.Text + "'r'n";
            var Cleaningcontent ="["+ _cleaningNamelLabel.Text+"]" +"'r'n"+_cleaningIdLabel21.Text+ 
                _durCleaningTextbox.Text + "'r'n"+ _cleaningLabelId22.Text+
                _timeValveOnTextbox.Text + "'r'n"+ _cleaningLabelId23.Text+_timeValveOffTextBox.Text+"'r'n";
            var Calibratecontent = "[" +_calibrateNameLabel.Text+ "]"+"'r'n"+_calibrateIDLabel31.Text+_contentLeftTextBox.Text+
                "'r'n"+ _calibrateIDLabel32.Text+_calibrateLeftTextBox.Text+"'r'n"+_calibrateIDLabel33.Text+_contentRightTextBox.Text+
                "'r'n" + _calibrateIDLabel34.Text + _calibrateRightTextBox.Text + "'r'n";
            var Conductcontent = "[" + _conductName.Text + "]" + "'r'n" + _conductIdLabel41.Text + _factorLeftTextBox.Text +
                                 "'r'n"
                                 + _conductIdLabel42.Text + _offsetLeftTextBox.Text + "'r'n" + _conductIdLabel43.Text +
                                 _factorRightTextBox.Text + "'r'n"
                                 + _conductIdLabel44.Text + _offsetRightTextBox.Text + "'r'n" + _conductIdLabel45.Text +
                                 _levelLeftTextBox.Text + "'r'n"
                                 + _conductIdLabel46.Text + _levelRightTextBox.Text + "'r'n";
            var Generalcontent = "[" + _generalName.Text + "]" + "'r'n" + _generalIdLabel51.Text + _typeOfValveTextBox.Text +
                                 "'r'n" +
                                 _generalIdLabel52.Text + _indicatorTextBox.Text + "'r'n" + _generalIdLabel53.Text +
                                 _inverseOutputTextBox.Text +
                                 "'r'n" + _generalIdLabel54.Text + _restartTimeTextBox.Text + "'r'n" +
                                 _generalIdLabel55.Text + _waterTimeTextBox.Text +
                                 "'r'n" + _generalIdLabel56.Text + _gateDelayTextbox.Text + "'r'n";
            var Pulsationcontent = "[" + _pulsationName.Text + "]" + "'r'n" + _pulsationIdLabel61.Text +
                                   _pulsationTextBox.Text + "'r'n" +
                                   _pulsationIdLabel62.Text + _ratioFrontTextBox.Text + "'r'n" +
                                   _pulsationIdLabel63.Text + _ratioBackTextBox.Text + "'r'n" +
                                   _pulsationIdLabel64.Text + _stimulationTextBox.Text + "'r'n" +
                                   _pulsationIdLabel65.Text + _stimFrontTextBox.Text + "'r'n" +
                                   _pulsationIdLabel66.Text + _stimBackTextBox.Text + "'r'n" + _pulsationIdLabel67.Text +
                                   _stimulationDurTextBox.Text + "'r'n";

            byte[] array = ComPort.StringToBytes(2+"'r'n"+Acrcontent+"'r'n"+Cleaningcontent + "'r'n" + Calibratecontent+"'r'n"+Conductcontent+"'r'n"+Generalcontent+"'r'n"+Pulsationcontent+3);

            try
            {
                _comport.WriteBytes(array);
            }
            catch(Exception exc)
            {
                MessageBox.Show("Error {1}: "+ exc);
            }

            try
            {
                _comport.ReadBytes(array, array.Length, 1000);
            }
            catch(Exception exc)
            {
                MessageBox.Show("Error {2}" + exc);
            }
            //string result = Encoding.ASCII.GetString(array);
            //MessageBox.Show(result);
        }
       }

这是我的通信代码:

namespace Communication
{
    public class ComPort
    {
        private readonly SerialPort _serialPort;
        public ComPort(string portname, int baudRate)
        {
            _serialPort = new SerialPort();
            _serialPort.PortName = portname;  <-----
            _serialPort.BaudRate = baudRate;
            _serialPort.StopBits = StopBits.One;
            _serialPort.DataBits = 8;
            _serialPort.Parity = Parity.None;
            _serialPort.Handshake = Handshake.None;

            // _serialPort.WriteBufferSize = 1;
            _serialPort.DtrEnable = true;
            _serialPort.RtsEnable = true;
            _serialPort.Open();
            _serialPort.ReadTimeout = 20000;
            _serialPort.WriteTimeout = 20000;
        }
        public void Clear()
        {
            while (ReadByte() != -1)
                continue;
        }
        private byte[] _array = new byte[] {0};
        public void WriteByte(byte value)
        {
            _array[0] = value;
            _serialPort.Write(_array, 0, 1);
            // _serialPort.BaseStream.WriteByte(value);
            _serialPort.BaseStream.Flush();
        }
        public void WriteBytes(byte[] array)
        {
            _serialPort.Write(array, 0, array.Length);
        }
        public void WriteBytes(byte[] array, int index, int length )
        {
            _serialPort.Write(array, index, length);
        }
        private int _readTimeOut = -1;
        public int ReadByte(int timeOut = 200)
        {
            if (timeOut != _readTimeOut)
                _serialPort.ReadTimeout = _readTimeOut = timeOut;
            try
            {
                //return _serialPort.BaseStream.ReadByte();
                return _serialPort.ReadByte();
                // _serialPort.Read(array, 0, 1);
                // return array[0];
            }
            catch (TimeoutException)
            {
                return -1;
            }
        }
        public int ReadBytes(byte[] array, int length, int timeOut = 200)
        {
            if (timeOut != _readTimeOut)
                _serialPort.ReadTimeout = _readTimeOut = timeOut;
            try
            {
                //return _serialPort.BaseStream.ReadByte();
                int bytesRead = 0;
                while ( bytesRead < length )
                    bytesRead += _serialPort.Read(array, bytesRead, length - bytesRead);
                // _serialPort.Read(array, 0, 1);
                // return array[0];
                return bytesRead;
            }
            catch (TimeoutException)
            {
                return -1;
            }
        }
        /// <summary>
        /// sends string followed by CR - LF
        /// </summary>
        /// <param name="line"></param>
        public void WriteLine(String line)
        {
            WriteBytes(StringToBytes(line + "'r'n"));
        }
        public static byte[] StringToBytes(string input)
        {
            return Encoding.ASCII.GetBytes(input);
        }
        public void Close()
        {
            try
            {
                _serialPort.DtrEnable = false;
                _serialPort.RtsEnable = false;
                _serialPort.Close();
            }
            catch(IOException)
            {
            }
        }
        public bool Dtr
        {
            get { return _serialPort.DtrEnable; }
            set { _serialPort.DtrEnable = value; }
        }
        public bool Rts
        {
            get { return _serialPort.RtsEnable; }
            set { _serialPort.RtsEnable = value; }
        }
    }
}

有人可以向我解释问题是什么吗?提前致谢

可能的安慰者:

            InitializeComponent();
            SetBaudrate();
            LoadSettings(false);
            LoadTextBoxes();
            LoadComportName();
            _comtimer.Tick += OnComtimerOnTick;
            _comtimer.Interval = 2000;
            _comtimer.Start();

            LoadComportName();
            Thread.Sleep(1000);
            var portname = GetCurrentComPort();

                _comport = new ComPort("COM6", 9600);

但是当我这样做时,另一个错误即将到来:

Value cannot be null.
Parameter name: PortName

这出现在箭头所在的第二段代码中。

空引用:对象引用未设置为对象的实例

可能在启动时没有选择 comport,所以_comport永远不会被创建,你应该在使用之前检查是否创建了 comport:if (_comport != null) ...


更新:

我认为您应该创建一个按钮,而不是在组合框选择更改时默认连接。

public void buttonConnect_Click(object sender, EventArgs e)
{
    // check if the comport is created, else show a message and return,
    TryDisconnect();
    var portname = GetCurrentComPort();
    if (portname == null)
        return;
    try
    {
        _comport = new ComPort(portname, 9600);
    }
    catch(Exception exception)
    {
        // try to create a better message here :-)
        MessageBox.Show("Something went wrong....");
    }
}
public void buttonDisconnect_Click(object sender, EventArgs e)
{
    TryDisconnect();
}
public void TryDisconnect()
{
    if( _comport != null)
    {
        _comport.Dispose();
        _comport = null;
    }
}

同样为此:

    private void SendSettingsButtonClick(object sender, System.EventArgs e)
    {
        // check the _comPort instance first, if not assigned, leave a message..
        if(_comPort == null)
        {
            MessageBox.Show("The comport is not initialized");
            return;
        }
        var availablePorts = _systemPorts;
        if (availablePorts != null && availablePorts.Any())
        {
           SaveSettings();
           SendMessageTest();
        }
        else
        {
            _comPortComboBox.Text = "No Ports are available";
        }
    }

我有一个提示给你,尝试分离消息的标记/构造,这里是你可以怎么做的。我没有更改所有代码,只有一些示例:

我会创建一个结构/类来保存所有信息

    public struct AcrContentInfo
    {
        public string AcrName;
        public string AcrId11;
        public string StartRemoval;
        public string AcrId12;
        public string RemovalTime;
        public string AcrId13;
        public string RemovalDelay;
        // markup the information:
        public override string ToString()
        {
            return string.Format(
                "[{0}]'r'n{1}{2}'r'n{3}{4}'r'n{5}{6}'r'n",
                AcrName,
                AcrId11, StartRemoval,
                AcrId12, RemovalTime,
                AcrId13, RemovalDelay);
        }
    }
    private void SendMessageTest()
    {
        // Instead of:
        //var Acrcontent = "[" + _acrNameLabel.Text + "]" + "'r'n" + _acrIdLabel11.Text + _startRemovalTextBox.Text + "'r'n"
        //                     + _acrIdLabel12.Text + _removalTimeTextBox.Text + "'r'n" + _acrIdLabel13.Text +
        //                _removalDelayTextBox.Text + "'r'n";

        // I would use this instead, this way it wil be easier to maintain different versions.
        // The code using the struct isn't responsible for markup
        // Create the struct and fillin the fields.
        AcrContentInfo acrContentInfo = new AcrContentInfo
        {
            AcrName = _acrNameLabel.Text,
            AcrId11 = _acrIdLabel11.Text,
            StartRemoval = _startRemovalTextBox.Text,
            AcrId12 = _acrIdLabel12.Text,
            RemovalTime = _removalTimeTextBox.Text,
            AcrId13 = _acrIdLabel13.Text,
            RemovalDelay = _removalDelayTextBox.Text
        };
        // if there is a new version of the protocol, you can create something like this
        // AcrContentInfoV2 acrContentInfo = new AcrContentInfoV2

        // call the tostring, (create a markup)
        var Acrcontent = acrContentInfo.ToString();
        // --- old code ---
        var Cleaningcontent = "[" + _cleaningNamelLabel.Text + "]" + "'r'n" + _cleaningIdLabel21.Text +
            _durCleaningTextbox.Text + "'r'n" + _cleaningLabelId22.Text +
            _timeValveOnTextbox.Text + "'r'n" + _cleaningLabelId23.Text + _timeValveOffTextBox.Text + "'r'n";
        var Calibratecontent = "[" + _calibrateNameLabel.Text + "]" + "'r'n" + _calibrateIDLabel31.Text + _contentLeftTextBox.Text +
            "'r'n" + _calibrateIDLabel32.Text + _calibrateLeftTextBox.Text + "'r'n" + _calibrateIDLabel33.Text + _contentRightTextBox.Text +
            "'r'n" + _calibrateIDLabel34.Text + _calibrateRightTextBox.Text + "'r'n";
        var Conductcontent = "[" + _conductName.Text + "]" + "'r'n" + _conductIdLabel41.Text + _factorLeftTextBox.Text +
                             "'r'n"
                             + _conductIdLabel42.Text + _offsetLeftTextBox.Text + "'r'n" + _conductIdLabel43.Text +
                             _factorRightTextBox.Text + "'r'n"
                             + _conductIdLabel44.Text + _offsetRightTextBox.Text + "'r'n" + _conductIdLabel45.Text +
                             _levelLeftTextBox.Text + "'r'n"
                             + _conductIdLabel46.Text + _levelRightTextBox.Text + "'r'n";
        var Generalcontent = "[" + _generalName.Text + "]" + "'r'n" + _generalIdLabel51.Text + _typeOfValveTextBox.Text +
                             "'r'n" +
                             _generalIdLabel52.Text + _indicatorTextBox.Text + "'r'n" + _generalIdLabel53.Text +
                             _inverseOutputTextBox.Text +
                             "'r'n" + _generalIdLabel54.Text + _restartTimeTextBox.Text + "'r'n" +
                             _generalIdLabel55.Text + _waterTimeTextBox.Text +
                             "'r'n" + _generalIdLabel56.Text + _gateDelayTextbox.Text + "'r'n";
        var Pulsationcontent = "[" + _pulsationName.Text + "]" + "'r'n" + _pulsationIdLabel61.Text +
                               _pulsationTextBox.Text + "'r'n" +
                               _pulsationIdLabel62.Text + _ratioFrontTextBox.Text + "'r'n" +
                               _pulsationIdLabel63.Text + _ratioBackTextBox.Text + "'r'n" +
                               _pulsationIdLabel64.Text + _stimulationTextBox.Text + "'r'n" +
                               _pulsationIdLabel65.Text + _stimFrontTextBox.Text + "'r'n" +
                               _pulsationIdLabel66.Text + _stimBackTextBox.Text + "'r'n" + _pulsationIdLabel67.Text +
                               _stimulationDurTextBox.Text + "'r'n";
        // instad of:
        //byte[] array = ComPort.StringToBytes(2+"'r'n"+Acrcontent+"'r'n"+Cleaningcontent + "'r'n" + Calibratecontent+"'r'n"+Conductcontent+"'r'n"+Generalcontent+"'r'n"+Pulsationcontent+3);
        // I always try not to make very long lines of code.
        // A stringbuilder is much more efficient building strings.
        // I would:
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("2");
        sb.AppendLine("Acrcontent");
        sb.AppendLine("Cleaningcontent");
        sb.AppendLine("Calibratecontent");
        sb.AppendLine("Conductcontent");
        sb.AppendLine("Generalcontent");
        sb.AppendLine("Pulsationcontent");
        sb.AppendLine("3");
        // why make the comport class responsible for the encoding type. _ComPort.StringToBytes_
        byte[] array = Encoding.UTF8.GetBytes(sb.ToString());

        try
        {
            _comport.WriteBytes(array);
            // only read when write was succeed?
            _comport.ReadBytes(array, array.Length, 1000);
        }
        catch (Exception exc)
        {
            MessageBox.Show("Error {1}: " + exc);
        }
    }

这些只是的想法,旨在具有建设性。(其他观点)快乐编码..

在调用方法或访问方法的属性之前,必须实例化_comport。

也许在

            var portname = GetCurrentComPort();
            if (portname != null)
            {
                _comport = new ComPort("COM6", 9600);
            }

portname 为 null,则_comport未实例化。 您可以跟踪它并检查它是否有值。

是 为_comport赋值

_comport=空;