让我解释一下我的问题,
我有一个串行通信代码,这段代码可以将文本框中的值发送到设备或者当我测试到另一台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
这是箭头所在的第二段代码。
答案 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;