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

时间:2013-09-23 06:55:11

标签: c# serial-port

让我解释一下我的问题,

我有一个串行通信代码,这段代码可以将文本框中的值发送到设备或者当我测试到另一台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

这是箭头所在的第二段代码。

3 个答案:

答案 0 :(得分:1)

可能在启动时没有选择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);
        }
    }

这些只是我的想法,并且意味着具有建设性。 (其他观点)快乐编码..

答案 1 :(得分:0)

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

也许在

            var portname = GetCurrentComPort();

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

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

答案 2 :(得分:0)

是为_comport指定一个值,如

_comport = NULL;