C# 尝试关闭串行端口或exí时出现异常;t应用
我有一个应用程序,通过串口读取XBee帧,并在richtextbox中显示帧。它还在图表中显示2个模拟通道(温度读数),并实时更新 我遇到应用程序读取串行端口的速度快于输入字节的速度的问题,因此我添加了以下行:C# 尝试关闭串行端口或exí时出现异常;t应用,c#,multithreading,serial-communication,xbee,real-time-data,C#,Multithreading,Serial Communication,Xbee,Real Time Data,我有一个应用程序,通过串口读取XBee帧,并在richtextbox中显示帧。它还在图表中显示2个模拟通道(温度读数),并实时更新 我遇到应用程序读取串行端口的速度快于输入字节的速度的问题,因此我添加了以下行: while (comPort.BytesToRead < (inLength + 4)) Thread.Sleep(10); while(comPort.BytesToRead3) { 组件读取(incByte,0,3); if(incByte[0]==0x7E) { lengt
while (comPort.BytesToRead < (inLength + 4)) Thread.Sleep(10);
while(comPort.BytesToRead<(inLength+4))Thread.Sleep(10);
这解决了这个问题,但现在我无法关闭串行端口或退出应用程序,而没有收到以下消息:“System.dll中发生了类型为'System.InvalidOperationException'的未处理异常附加信息:端口已关闭。”
我怀疑这是一个多线程问题,但如何解决它呢?我在一篇类似的文章中看到,使用BeginInvoke而不是Invoke应该可以解决这个问题,但我已经在使用它了
代码如下:
namespace SerialTest
{
public partial class frmMain : Form
{
delegate void SetTextCallback(string text);
delegate void SetChartCallback(double a, double b);
string inRawFrame = String.Empty;
double temp1 = 0;
double temp2 = 0;
public frmMain()
{
InitializeComponent();
}
private void btnGetSerialPorts_Click(object sender, EventArgs e)
{
if(btnGetSerialPorts.Text == "Open")
{
btnGetSerialPorts.Text = "Close";
comPort.PortName = Convert.ToString(cboPorts.Text);
comPort.BaudRate = Convert.ToInt32(cboBaudRate.Text);
comPort.ReadTimeout = 4000;
comPort.WriteTimeout = 6000;
if (!comPort.IsOpen)
{
try
{
comPort.Open();
cboPorts.Enabled = false;
cboBaudRate.Enabled = false;
}
catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
}
else if (btnGetSerialPorts.Text == "Close")
{
btnGetSerialPorts.Text = "Open";
comPort.Close();
cboPorts.Enabled = true;
cboBaudRate.Enabled = true;
}
}
private void Form1_Load(object sender, EventArgs e)
{
string[] arrayComPortsNames = null;
int index = 0;
string comPortName = null;
arrayComPortsNames = SerialPort.GetPortNames();
Array.Sort(arrayComPortsNames);
while (!((arrayComPortsNames[index] == comPortName) || (index == arrayComPortsNames.GetUpperBound(0))))
{
cboPorts.Items.Add(arrayComPortsNames[index]);
index++;
}
comPortName = arrayComPortsNames[0];
cboPorts.Text = comPortName;
cboBaudRate.Items.Add(9600);
cboBaudRate.Items.Add(14400);
cboBaudRate.Items.Add(19200);
cboBaudRate.Items.Add(38400);
cboBaudRate.Items.Add(57600);
cboBaudRate.Items.Add(115200);
cboBaudRate.Items.ToString();
cboBaudRate.Text = cboBaudRate.Items[5].ToString();
}
private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
byte[] incByte = new byte[3];
int length = 0;
if(comPort.BytesToRead > 3)
{
comPort.Read(incByte, 0, 3);
if (incByte[0] == 0x7E)
{
length = (incByte[1] << 8) + incByte[2];
byte[] buffer = new byte[length+4];
buffer[0] = incByte[0];
buffer[1] = incByte[1];
buffer[2] = incByte[2];
ReadFrame(buffer, length, DateTime.Now);
temp1 = ReadTemp(buffer, 1);
temp2 = ReadTemp(buffer, 2);
DisplayFrame();
UpdateChart();
}
}
}
private void ReadFrame(byte[] inBuffer, int inLength, DateTime time)
{
while (comPort.BytesToRead < (inLength + 4)) Thread.Sleep(10);
comPort.Read(inBuffer, 3, (inBuffer.Length - 3));
inRawFrame = time + " " + BitConverter.ToString(inBuffer).Replace("-", " ");
}
private void DisplayFrame()
{
if (rtbIncomingData.InvokeRequired)
{
rtbIncomingData.BeginInvoke(new SetTextCallback(SetText), new object[] { inRawFrame });
}
else
{
SetText(inRawFrame);
}
}
private void SetText(string text)
{
this.rtbIncomingData.AppendText(text + Environment.NewLine);
}
private double ReadTemp(byte[] data, int channel)
{
if(data[3] == 0x92)
{
if(channel == 1)
{
return ((((data[19] << 8) + data[20]) * 1.2 / 1023) - 0.5) * 100.0;
}
else
{
return ((((data[21] << 8) + data[22]) * 1.2 / 1023) - 0.5) * 100.0;
}
}
else
return 100;
}
private void UpdateChart()
{
if (chart1.InvokeRequired)
chart1.BeginInvoke(new SetChartCallback(SetChart), new object[] { temp1, temp2 });
else
SetChart(temp1, temp2);
}
private void SetChart(double val1, double val2)
{
chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Format = "HH:mm:ss";
chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.LineColor = Color.LightGray;
chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.LineColor = Color.LightGray;
chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Font = new Font("Consolas", 8);
chart1.ChartAreas["ChartArea1"].AxisY.LabelStyle.Font = new Font("Consolas", 8);
chart1.ChartAreas["ChartArea1"].AxisY.Maximum = 30;
chart1.ChartAreas["ChartArea1"].AxisY.Minimum = 10;
chart1.ChartAreas["ChartArea1"].AxisY.Interval = 1;
chart1.Series[0].Name = "Temp 1";
chart1.Series[1].Name = "Temp 2";
chart1.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[0].MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Diamond;
chart1.Series[0].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime;
chart1.Series[1].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[1].MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Diamond;
chart1.Series[1].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime;
chart1.Series[0].Points.AddXY(DateTime.Now, val1);
chart1.Series[1].Points.AddXY(DateTime.Now, val2);
}
}
}
namespace序列化测试
{
公共部分类名称:表单
{
委托无效SetTextCallback(字符串文本);
委托无效SetChartCallback(双a,双b);
rawFrame中的字符串=string.Empty;
双temp1=0;
双temp2=0;
公共财政收入()
{
初始化组件();
}
私有void btnGetSerialPorts_单击(对象发送者,事件参数e)
{
如果(btngetserialport.Text==“打开”)
{
btngetserialport.Text=“关闭”;
comPort.PortName=Convert.ToString(cboPorts.Text);
comPort.BaudRate=Convert.ToInt32(cboBaudRate.Text);
comPort.ReadTimeout=4000;
comPort.WriteTimeout=6000;
如果(!comPort.IsOpen)
{
尝试
{
comPort.Open();
cboPorts.Enabled=false;
cbobauddrate.Enabled=false;
}
捕获(未经授权的访问例外)
{
MessageBox.Show(例如Message);
}
}
}
else if(btngetserialport.Text==“关闭”)
{
btngetserialport.Text=“打开”;
comPort.Close();
cboPorts.Enabled=true;
cboBaudRate.Enabled=true;
}
}
私有void Form1\u加载(对象发送方、事件参数e)
{
字符串[]arrayComPortsNames=null;
int指数=0;
字符串comPortName=null;
arrayComPortsNames=SerialPort.GetPortNames();
Array.Sort(arrayComPortsNames);
而(!((arrayComPortsNames[index]==comPortName)| |(index==arrayComPortsNames.GetUpperBound(0)))
{
cboPorts.Items.Add(arrayComPortsNames[索引]);
索引++;
}
comPortName=arrayComPortsNames[0];
cboPorts.Text=comPortName;
cboBaudRate.Items.Add(9600);
CBOBauddrate.Items.Add(14400);
cboBaudRate.Items.Add(19200年);
CBOBauddrate.Items.Add(38400);
cbobudrate.Items.Add(57600);
CBOBauddrate.Items.Add(115200);
cboBaudRate.Items.ToString();
cboBaudRate.Text=cboBaudRate.Items[5].ToString();
}
private void comPort_DataReceived(对象发送方,SerialDataReceivedEventArgs e)
{
SerialPort sp=(SerialPort)发送方;
字节[]incByte=新字节[3];
整数长度=0;
如果(comPort.BytesToRead>3)
{
组件读取(incByte,0,3);
if(incByte[0]==0x7E)
{
length=(incByte[1]如果在ReadFrame()
仍在等待字节时关闭串行端口,则最终会在关闭的串行端口上检查BytesToRead
。可能改用此版本:
private void ReadFrame(byte[] inBuffer, int inLength, DateTime time)
{
while (comPort.IsOpen)
{
if (comPort.BytestoRead >= inLength + 4)
{
comPort.Read(inBuffer, 3, (inBuffer.Length - 3));
inRawFrame = time + " " + BitConverter.ToString(inBuffer).Replace("-", " ");
return;
}
Thread.Sleep(10);
}
}
如果在等待帧时串行端口关闭,它将退出,并且仅在端口仍然打开时检查BytesToRead
。太好了!!完成了。谢谢!!